* Re: [PATCH v7 5/5] nvmet-tcp: Support KeyUpdate
From: Christoph Hellwig @ 2026-03-20 7:53 UTC (permalink / raw)
To: alistair23
Cc: chuck.lever, hare, kernel-tls-handshake, netdev, linux-kernel,
linux-doc, linux-nvme, linux-nfs, kbusch, axboe, hch, sagi, kch,
hare, Alistair Francis
In-Reply-To: <20260304053500.590630-6-alistair.francis@wdc.com>
> static void nvmet_tcp_free_cmd_buffers(struct nvmet_tcp_cmd *cmd);
> +#ifdef CONFIG_NVME_TARGET_TCP_TLS
> +static int nvmet_tcp_tls_handshake(struct nvmet_tcp_queue *queue,
> + enum handshake_key_update_type keyupdate);
> +#endif
Can we find a way to just avoid the ifdefered here and just rely on
compiler dead code elimination?
> +#ifdef CONFIG_NVME_TARGET_TCP_TLS
> +static bool nvmet_tls_key_expired(struct nvmet_tcp_queue *queue, int ret)
> +{
> + return ret == -EKEYEXPIRED &&
> + queue->state != NVMET_TCP_Q_DISCONNECTING &&
> + queue->state != NVMET_TCP_Q_TLS_HANDSHAKE;
> +}
> +#else
> +static bool nvmet_tls_key_expired(struct nvmet_tcp_queue *queue, int ret)
> +{
> + return false;
> +}
> +#endif
This is a pretty clear candidate for IS_ENABLED().
> + spin_lock_bh(&queue->state_lock);
> + if (queue->state == NVMET_TCP_Q_TLS_HANDSHAKE) {
> + /* Socket closed during handshake */
> + tls_handshake_cancel(queue->sock->sk);
> + }
> + if (queue->state != NVMET_TCP_Q_DISCONNECTING) {
> + queue->state = NVMET_TCP_Q_DISCONNECTING;
> + kref_put(&queue->kref, nvmet_tcp_release_queue);
> + }
switch on the queue state?
> + ret = nvmet_tcp_tls_handshake(queue, HANDSHAKE_KEY_UPDATE_TYPE_RECEIVED);
Overly lone line.
> if (unlikely(ret < 0)) {
> + if (nvmet_tls_key_expired(queue, ret))
> + goto done;
This has extra indentation.
^ permalink raw reply
* RE: [PATCH net-next v3 09/13] iavf: convert to ndo_set_rx_mode_async
From: Loktionov, Aleksandr @ 2026-03-20 7:53 UTC (permalink / raw)
To: Stanislav Fomichev, netdev@vger.kernel.org
Cc: davem@davemloft.net, edumazet@google.com, kuba@kernel.org,
pabeni@redhat.com, horms@kernel.org, corbet@lwn.net,
skhan@linuxfoundation.org, andrew+netdev@lunn.ch,
michael.chan@broadcom.com, pavan.chebbi@broadcom.com,
Nguyen, Anthony L, Kitszel, Przemyslaw, saeedm@nvidia.com,
tariqt@nvidia.com, mbloch@nvidia.com, alexanderduyck@fb.com,
kernel-team@meta.com, johannes@sipsolutions.net,
sd@queasysnail.net, jianbol@nvidia.com, dtatulea@nvidia.com,
mohsin.bashr@gmail.com, Keller, Jacob E, willemb@google.com,
skhawaja@google.com, bestswngs@gmail.com, kees@kernel.org,
linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org,
intel-wired-lan@lists.osuosl.org, linux-rdma@vger.kernel.org,
linux-wireless@vger.kernel.org, linux-kselftest@vger.kernel.org,
leon@kernel.org
In-Reply-To: <20260320012501.2033548-10-sdf@fomichev.me>
> -----Original Message-----
> From: Stanislav Fomichev <sdf@fomichev.me>
> Sent: Friday, March 20, 2026 2:25 AM
> To: netdev@vger.kernel.org
> Cc: davem@davemloft.net; edumazet@google.com; kuba@kernel.org;
> pabeni@redhat.com; horms@kernel.org; corbet@lwn.net;
> skhan@linuxfoundation.org; andrew+netdev@lunn.ch;
> michael.chan@broadcom.com; pavan.chebbi@broadcom.com; Nguyen, Anthony
> L <anthony.l.nguyen@intel.com>; Kitszel, Przemyslaw
> <przemyslaw.kitszel@intel.com>; saeedm@nvidia.com; tariqt@nvidia.com;
> mbloch@nvidia.com; alexanderduyck@fb.com; kernel-team@meta.com;
> johannes@sipsolutions.net; sd@queasysnail.net; jianbol@nvidia.com;
> dtatulea@nvidia.com; sdf@fomichev.me; mohsin.bashr@gmail.com; Keller,
> Jacob E <jacob.e.keller@intel.com>; willemb@google.com;
> skhawaja@google.com; bestswngs@gmail.com; Loktionov, Aleksandr
> <aleksandr.loktionov@intel.com>; kees@kernel.org; linux-
> doc@vger.kernel.org; linux-kernel@vger.kernel.org; intel-wired-
> lan@lists.osuosl.org; linux-rdma@vger.kernel.org; linux-
> wireless@vger.kernel.org; linux-kselftest@vger.kernel.org;
> leon@kernel.org
> Subject: [PATCH net-next v3 09/13] iavf: convert to
> ndo_set_rx_mode_async
>
> Convert iavf from ndo_set_rx_mode to ndo_set_rx_mode_async.
> iavf_set_rx_mode now takes explicit uc/mc list parameters and uses
> __hw_addr_sync_dev on the snapshots instead of __dev_uc_sync and
> __dev_mc_sync.
>
> The iavf_configure internal caller passes the real lists directly.
>
> Cc: Tony Nguyen <anthony.l.nguyen@intel.com>
> Cc: Przemek Kitszel <przemyslaw.kitszel@intel.com>
> Signed-off-by: Stanislav Fomichev <sdf@fomichev.me>
> ---
> drivers/net/ethernet/intel/iavf/iavf_main.c | 14 +++++++++-----
> 1 file changed, 9 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c
> b/drivers/net/ethernet/intel/iavf/iavf_main.c
> index 7925ee152c76..6632d35ad0fe 100644
> --- a/drivers/net/ethernet/intel/iavf/iavf_main.c
> +++ b/drivers/net/ethernet/intel/iavf/iavf_main.c
> @@ -1147,14 +1147,18 @@ bool iavf_promiscuous_mode_changed(struct
> iavf_adapter *adapter)
> /**
> * iavf_set_rx_mode - NDO callback to set the netdev filters
> * @netdev: network interface device structure
> + * @uc: snapshot of uc address list
> + * @mc: snapshot of mc address list
> **/
> -static void iavf_set_rx_mode(struct net_device *netdev)
> +static void iavf_set_rx_mode(struct net_device *netdev,
> + struct netdev_hw_addr_list *uc,
> + struct netdev_hw_addr_list *mc)
> {
> struct iavf_adapter *adapter = netdev_priv(netdev);
>
> spin_lock_bh(&adapter->mac_vlan_list_lock);
> - __dev_uc_sync(netdev, iavf_addr_sync, iavf_addr_unsync);
> - __dev_mc_sync(netdev, iavf_addr_sync, iavf_addr_unsync);
> + __hw_addr_sync_dev(uc, netdev, iavf_addr_sync,
> iavf_addr_unsync);
> + __hw_addr_sync_dev(mc, netdev, iavf_addr_sync,
> iavf_addr_unsync);
> spin_unlock_bh(&adapter->mac_vlan_list_lock);
>
> spin_lock_bh(&adapter->current_netdev_promisc_flags_lock);
> @@ -1207,7 +1211,7 @@ static void iavf_configure(struct iavf_adapter
> *adapter)
> struct net_device *netdev = adapter->netdev;
> int i;
>
> - iavf_set_rx_mode(netdev);
> + iavf_set_rx_mode(netdev, &netdev->uc, &netdev->mc);
>
> iavf_configure_tx(adapter);
> iavf_configure_rx(adapter);
> @@ -5150,7 +5154,7 @@ static const struct net_device_ops
> iavf_netdev_ops = {
> .ndo_open = iavf_open,
> .ndo_stop = iavf_close,
> .ndo_start_xmit = iavf_xmit_frame,
> - .ndo_set_rx_mode = iavf_set_rx_mode,
> + .ndo_set_rx_mode_async = iavf_set_rx_mode,
> .ndo_validate_addr = eth_validate_addr,
> .ndo_set_mac_address = iavf_set_mac,
> .ndo_change_mtu = iavf_change_mtu,
> --
> 2.53.0
Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
^ permalink raw reply
* RE: [PATCH net-next v3 08/13] bnxt: use snapshot in bnxt_cfg_rx_mode
From: Loktionov, Aleksandr @ 2026-03-20 7:51 UTC (permalink / raw)
To: Stanislav Fomichev, netdev@vger.kernel.org
Cc: davem@davemloft.net, edumazet@google.com, kuba@kernel.org,
pabeni@redhat.com, horms@kernel.org, corbet@lwn.net,
skhan@linuxfoundation.org, andrew+netdev@lunn.ch,
michael.chan@broadcom.com, pavan.chebbi@broadcom.com,
Nguyen, Anthony L, Kitszel, Przemyslaw, saeedm@nvidia.com,
tariqt@nvidia.com, mbloch@nvidia.com, alexanderduyck@fb.com,
kernel-team@meta.com, johannes@sipsolutions.net,
sd@queasysnail.net, jianbol@nvidia.com, dtatulea@nvidia.com,
mohsin.bashr@gmail.com, Keller, Jacob E, willemb@google.com,
skhawaja@google.com, bestswngs@gmail.com, kees@kernel.org,
linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org,
intel-wired-lan@lists.osuosl.org, linux-rdma@vger.kernel.org,
linux-wireless@vger.kernel.org, linux-kselftest@vger.kernel.org,
leon@kernel.org
In-Reply-To: <20260320012501.2033548-9-sdf@fomichev.me>
> -----Original Message-----
> From: Stanislav Fomichev <sdf@fomichev.me>
> Sent: Friday, March 20, 2026 2:25 AM
> To: netdev@vger.kernel.org
> Cc: davem@davemloft.net; edumazet@google.com; kuba@kernel.org;
> pabeni@redhat.com; horms@kernel.org; corbet@lwn.net;
> skhan@linuxfoundation.org; andrew+netdev@lunn.ch;
> michael.chan@broadcom.com; pavan.chebbi@broadcom.com; Nguyen, Anthony
> L <anthony.l.nguyen@intel.com>; Kitszel, Przemyslaw
> <przemyslaw.kitszel@intel.com>; saeedm@nvidia.com; tariqt@nvidia.com;
> mbloch@nvidia.com; alexanderduyck@fb.com; kernel-team@meta.com;
> johannes@sipsolutions.net; sd@queasysnail.net; jianbol@nvidia.com;
> dtatulea@nvidia.com; sdf@fomichev.me; mohsin.bashr@gmail.com; Keller,
> Jacob E <jacob.e.keller@intel.com>; willemb@google.com;
> skhawaja@google.com; bestswngs@gmail.com; Loktionov, Aleksandr
> <aleksandr.loktionov@intel.com>; kees@kernel.org; linux-
> doc@vger.kernel.org; linux-kernel@vger.kernel.org; intel-wired-
> lan@lists.osuosl.org; linux-rdma@vger.kernel.org; linux-
> wireless@vger.kernel.org; linux-kselftest@vger.kernel.org;
> leon@kernel.org
> Subject: [PATCH net-next v3 08/13] bnxt: use snapshot in
> bnxt_cfg_rx_mode
>
> With the introduction of ndo_set_rx_mode_async (as discussed in [0])
> we can call bnxt_cfg_rx_mode directly. Convert bnxt_cfg_rx_mode to use
> uc/mc snapshots and move its call in bnxt_sp_task to the section that
> resets BNXT_STATE_IN_SP_TASK. Switch to direct call in
> bnxt_set_rx_mode.
>
> 0:
> https://lore.kernel.org/netdev/CACKFLi=5vj8hPqEUKDd8RTw3au5G+zRgQEqjF+
> 6NZnyoNm90KA@mail.gmail.com/
>
> Cc: Michael Chan <michael.chan@broadcom.com>
> Cc: Pavan Chebbi <pavan.chebbi@broadcom.com>
> Signed-off-by: Stanislav Fomichev <sdf@fomichev.me>
> ---
> drivers/net/ethernet/broadcom/bnxt/bnxt.c | 26 ++++++++++++++--------
> -
> 1 file changed, 16 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
> b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
> index 225217b32e4b..12265bd7fda4 100644
> --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
> +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
> @@ -11039,7 +11039,8 @@ static int bnxt_setup_nitroa0_vnic(struct bnxt
> *bp)
> return rc;
> }
>
> -static int bnxt_cfg_rx_mode(struct bnxt *);
> +static int bnxt_cfg_rx_mode(struct bnxt *, struct netdev_hw_addr_list
> *,
> + struct netdev_hw_addr_list *);
> static bool bnxt_mc_list_updated(struct bnxt *, u32 *,
> const struct netdev_hw_addr_list *);
>
> @@ -11135,7 +11136,7 @@ static int bnxt_init_chip(struct bnxt *bp,
> bool irq_re_init)
> vnic->rx_mask |= mask;
> }
>
> - rc = bnxt_cfg_rx_mode(bp);
> + rc = bnxt_cfg_rx_mode(bp, &bp->dev->uc, &bp->dev->mc);
> if (rc)
> goto err_out;
>
> @@ -13610,11 +13611,12 @@ static void bnxt_set_rx_mode(struct
> net_device *dev,
> if (mask != vnic->rx_mask || uc_update || mc_update) {
> vnic->rx_mask = mask;
>
> - bnxt_queue_sp_work(bp, BNXT_RX_MASK_SP_EVENT);
> + bnxt_cfg_rx_mode(bp, uc, mc);
> }
> }
>
> -static int bnxt_cfg_rx_mode(struct bnxt *bp)
> +static int bnxt_cfg_rx_mode(struct bnxt *bp, struct
> netdev_hw_addr_list *uc,
> + struct netdev_hw_addr_list *mc)
> {
> struct net_device *dev = bp->dev;
> struct bnxt_vnic_info *vnic = &bp-
> >vnic_info[BNXT_VNIC_DEFAULT];
> @@ -13623,7 +13625,7 @@ static int bnxt_cfg_rx_mode(struct bnxt *bp)
> bool uc_update;
>
> netif_addr_lock_bh(dev);
> - uc_update = bnxt_uc_list_updated(bp, &dev->uc);
> + uc_update = bnxt_uc_list_updated(bp, uc);
> netif_addr_unlock_bh(dev);
>
> if (!uc_update)
> @@ -13639,10 +13641,10 @@ static int bnxt_cfg_rx_mode(struct bnxt *bp)
> vnic->uc_filter_count = 1;
>
> netif_addr_lock_bh(dev);
> - if (netdev_uc_count(dev) > (BNXT_MAX_UC_ADDRS - 1)) {
> + if (netdev_hw_addr_list_count(uc) > (BNXT_MAX_UC_ADDRS - 1)) {
> vnic->rx_mask |=
> CFA_L2_SET_RX_MASK_REQ_MASK_PROMISCUOUS;
> } else {
> - netdev_for_each_uc_addr(ha, dev) {
> + netdev_hw_addr_list_for_each(ha, uc) {
> memcpy(vnic->uc_list + off, ha->addr, ETH_ALEN);
> off += ETH_ALEN;
> vnic->uc_filter_count++;
> @@ -14600,6 +14602,7 @@ static void bnxt_ulp_restart(struct bnxt *bp)
> static void bnxt_sp_task(struct work_struct *work) {
> struct bnxt *bp = container_of(work, struct bnxt, sp_task);
> + struct net_device *dev = bp->dev;
>
> set_bit(BNXT_STATE_IN_SP_TASK, &bp->state);
> smp_mb__after_atomic();
> @@ -14613,9 +14616,6 @@ static void bnxt_sp_task(struct work_struct
> *work)
> bnxt_reenable_sriov(bp);
> }
>
> - if (test_and_clear_bit(BNXT_RX_MASK_SP_EVENT, &bp->sp_event))
> - bnxt_cfg_rx_mode(bp);
> -
> if (test_and_clear_bit(BNXT_RX_NTP_FLTR_SP_EVENT, &bp-
> >sp_event))
> bnxt_cfg_ntp_filters(bp);
> if (test_and_clear_bit(BNXT_HWRM_EXEC_FWD_REQ_SP_EVENT, &bp-
> >sp_event)) @@ -14680,6 +14680,12 @@ static void bnxt_sp_task(struct
> work_struct *work)
> /* These functions below will clear BNXT_STATE_IN_SP_TASK.
> They
> * must be the last functions to be called before exiting.
> */
> + if (test_and_clear_bit(BNXT_RX_MASK_SP_EVENT, &bp->sp_event)) {
> + bnxt_lock_sp(bp);
> + bnxt_cfg_rx_mode(bp, &dev->uc, &dev->mc);
> + bnxt_unlock_sp(bp);
> + }
> +
> if (test_and_clear_bit(BNXT_RESET_TASK_SP_EVENT, &bp-
> >sp_event))
> bnxt_reset(bp, false);
>
> --
> 2.53.0
Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
^ permalink raw reply
* Re: [PATCH v7 4/5] nvme-tcp: Support KeyUpdate
From: Christoph Hellwig @ 2026-03-20 7:51 UTC (permalink / raw)
To: Alistair Francis
Cc: Hannes Reinecke, chuck.lever, hare, kernel-tls-handshake, netdev,
linux-kernel, linux-doc, linux-nvme, linux-nfs, kbusch, axboe,
hch, sagi, kch, Alistair Francis
In-Reply-To: <CAKmqyKPdJ2bgT2JaXi_38obyFTjRQ_rR5EdGmP81so8MEJNRVw@mail.gmail.com>
On Wed, Mar 04, 2026 at 09:37:22PM +1000, Alistair Francis wrote:
> > I think a simple 'if' condition would be sufficient here, or do you have
> > handling of other TLS record types queued somewhere?
> > And we should log unhandled TLS records.
>
> I like this approach as it makes it really easy to handle more types
> in the future. I don't have any more record types queued anywhere so I
> can change it to an if statement.
Agreed. OTOH having more than a handful of lines in switches like this
is a always a bad idea, so factoring this out into a type-specific
helper would be much preferred.
^ permalink raw reply
* Re: [PATCH 09/14] drm/drv: Call drm_mode_config_create_state() by default
From: Maxime Ripard @ 2026-03-20 7:39 UTC (permalink / raw)
To: Laurent Pinchart
Cc: Maarten Lankhorst, Thomas Zimmermann, David Airlie, Simona Vetter,
Jonathan Corbet, Shuah Khan, Dmitry Baryshkov, Jyri Sarha,
Tomi Valkeinen, Andrzej Hajda, Neil Armstrong, Robert Foss,
Jonas Karlman, Jernej Skrabec, dri-devel, linux-doc, linux-kernel
In-Reply-To: <20260316163354.GN31604@killaraus.ideasonboard.com>
[-- Attachment #1: Type: text/plain, Size: 933 bytes --]
On Mon, Mar 16, 2026 at 06:33:54PM +0200, Laurent Pinchart wrote:
> On Tue, Mar 10, 2026 at 05:07:01PM +0100, Maxime Ripard wrote:
> > Almost all drivers, and our documented skeleton, call
> > drm_mode_config_reset() prior to calling drm_dev_register() to
> > initialize its DRM object states.
> >
> > Now that we have drm_mode_config_create_state() to create that initial
> > state if it doesn't exist, we can call it directly in
> > drm_dev_register(). That way, we know that the initial atomic state will
> > always be allocated without any boilerplate.
>
> Should most drivers now stop calling drm_mode_config_reset() at probe
> time ?
Yes, that's my intention. For the vast majority of them, reset is just
about allocating and committing a blank state anyway.
However, for the drivers that do need to reset the hardware, we should
keep the door open (and / or provide an alternative mechanism).
Maxime
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 273 bytes --]
^ permalink raw reply
* RE: [Intel-wired-lan] [PATCH net-next v3 03/13] net: introduce ndo_set_rx_mode_async and dev_rx_mode_work
From: Loktionov, Aleksandr @ 2026-03-20 7:13 UTC (permalink / raw)
To: Stanislav Fomichev, netdev@vger.kernel.org
Cc: davem@davemloft.net, edumazet@google.com, kuba@kernel.org,
pabeni@redhat.com, horms@kernel.org, corbet@lwn.net,
skhan@linuxfoundation.org, andrew+netdev@lunn.ch,
michael.chan@broadcom.com, pavan.chebbi@broadcom.com,
Nguyen, Anthony L, Kitszel, Przemyslaw, saeedm@nvidia.com,
tariqt@nvidia.com, mbloch@nvidia.com, alexanderduyck@fb.com,
kernel-team@meta.com, johannes@sipsolutions.net,
sd@queasysnail.net, jianbol@nvidia.com, dtatulea@nvidia.com,
mohsin.bashr@gmail.com, Keller, Jacob E, willemb@google.com,
skhawaja@google.com, bestswngs@gmail.com, kees@kernel.org,
linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org,
intel-wired-lan@lists.osuosl.org, linux-rdma@vger.kernel.org,
linux-wireless@vger.kernel.org, linux-kselftest@vger.kernel.org,
leon@kernel.org
In-Reply-To: <20260320012501.2033548-4-sdf@fomichev.me>
> -----Original Message-----
> From: Intel-wired-lan <intel-wired-lan-bounces@osuosl.org> On Behalf
> Of Stanislav Fomichev
> Sent: Friday, March 20, 2026 2:25 AM
> To: netdev@vger.kernel.org
> Cc: davem@davemloft.net; edumazet@google.com; kuba@kernel.org;
> pabeni@redhat.com; horms@kernel.org; corbet@lwn.net;
> skhan@linuxfoundation.org; andrew+netdev@lunn.ch;
> michael.chan@broadcom.com; pavan.chebbi@broadcom.com; Nguyen, Anthony
> L <anthony.l.nguyen@intel.com>; Kitszel, Przemyslaw
> <przemyslaw.kitszel@intel.com>; saeedm@nvidia.com; tariqt@nvidia.com;
> mbloch@nvidia.com; alexanderduyck@fb.com; kernel-team@meta.com;
> johannes@sipsolutions.net; sd@queasysnail.net; jianbol@nvidia.com;
> dtatulea@nvidia.com; sdf@fomichev.me; mohsin.bashr@gmail.com; Keller,
> Jacob E <jacob.e.keller@intel.com>; willemb@google.com;
> skhawaja@google.com; bestswngs@gmail.com; Loktionov, Aleksandr
> <aleksandr.loktionov@intel.com>; kees@kernel.org; linux-
> doc@vger.kernel.org; linux-kernel@vger.kernel.org; intel-wired-
> lan@lists.osuosl.org; linux-rdma@vger.kernel.org; linux-
> wireless@vger.kernel.org; linux-kselftest@vger.kernel.org;
> leon@kernel.org
> Subject: [Intel-wired-lan] [PATCH net-next v3 03/13] net: introduce
> ndo_set_rx_mode_async and dev_rx_mode_work
>
> Add ndo_set_rx_mode_async callback that drivers can implement instead
> of the legacy ndo_set_rx_mode. The legacy callback runs under the
> netif_addr_lock spinlock with BHs disabled, preventing drivers from
> sleeping. The async variant runs from a work queue with rtnl_lock and
> netdev_lock_ops held, in fully sleepable context.
>
> When __dev_set_rx_mode() sees ndo_set_rx_mode_async, it schedules
> dev_rx_mode_work instead of calling the driver inline. The work
> function takes two snapshots of each address list (uc/mc) under the
> addr_lock, then drops the lock and calls the driver with the work
> copies. After the driver returns, it reconciles the snapshots back to
> the real lists under the lock.
>
> Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
> Signed-off-by: Stanislav Fomichev <sdf@fomichev.me>
> ---
> Documentation/networking/netdevices.rst | 8 +++
> include/linux/netdevice.h | 20 ++++++
> net/core/dev.c | 95 +++++++++++++++++++++++-
> -
> 3 files changed, 116 insertions(+), 7 deletions(-)
>
> diff --git a/Documentation/networking/netdevices.rst
> b/Documentation/networking/netdevices.rst
> index 35704d115312..dc83d78d3b27 100644
> --- a/Documentation/networking/netdevices.rst
> +++ b/Documentation/networking/netdevices.rst
> @@ -289,6 +289,14 @@ struct net_device synchronization rules
> ndo_set_rx_mode:
> Synchronization: netif_addr_lock spinlock.
> Context: BHs disabled
...
> to
> +device
> + * and configure RX filtering.
> + * @dev: device
> + *
> + * When the device doesn't support unicast filtering it is put in
> +promiscuous
> + * mode while unicast addresses are present.
> */
> void __dev_set_rx_mode(struct net_device *dev) {
> const struct net_device_ops *ops = dev->netdev_ops;
>
> /* dev_open will call this function so the list will stay sane.
> */
> - if (!(dev->flags&IFF_UP))
> + if (!netif_up_and_present(dev))
> return;
>
> - if (!netif_device_present(dev))
> + if (ops->ndo_set_rx_mode_async) {
> + queue_work(rx_mode_wq, &dev->rx_mode_work);
> return;
This early return skips the legacy core fallback below.
Before this patch, __dev_set_rx_mode() continued into the
existing unicast-filter handling when the device did not
advertise IFF_UNICAST_FLT.
After this patch, any driver that implements
ndo_set_rx_mode_async but does not set IFF_UNICAST_FLT
will never hit that fallback path.
+ }
>
> if (!(dev->priv_flags & IFF_UNICAST_FLT)) {
> /* Unicast addresses changes may only happen under the
> rtnl, @@ -11708,6 +11772,16 @@ void netdev_run_todo(void)
>
> __rtnl_unlock();
>
...
> open_softirq(NET_TX_SOFTIRQ, net_tx_action);
> open_softirq(NET_RX_SOFTIRQ, net_rx_action);
>
> --
> 2.53.0
^ permalink raw reply
* Re: [PATCH v3 06/10] ACPI: APEI: GHES: move CXL CPER helpers
From: kernel test robot @ 2026-03-20 6:23 UTC (permalink / raw)
To: Ahmed Tiba, linux-acpi, devicetree, linux-cxl
Cc: oe-kbuild-all, Ahmed Tiba, Michael.Zhao2, robh, linux-arm-kernel,
Dmitry.Lamerov, rafael, conor, will, bp, catalin.marinas, krzk+dt,
linux-doc, mchehab+huawei, tony.luck
In-Reply-To: <20260318-topics-ahmtib01-ras_ffh_arm_internal_review-v3-6-48e6a1c249ef@arm.com>
Hi Ahmed,
kernel test robot noticed the following build warnings:
[auto build test WARNING on 2d1373e4246da3b58e1df058374ed6b101804e07]
url: https://github.com/intel-lab-lkp/linux/commits/Ahmed-Tiba/ACPI-APEI-GHES-share-macros-via-a-private-header/20260319-115432
base: 2d1373e4246da3b58e1df058374ed6b101804e07
patch link: https://lore.kernel.org/r/20260318-topics-ahmtib01-ras_ffh_arm_internal_review-v3-6-48e6a1c249ef%40arm.com
patch subject: [PATCH v3 06/10] ACPI: APEI: GHES: move CXL CPER helpers
config: x86_64-randconfig-122-20260320 (https://download.01.org/0day-ci/archive/20260320/202603201429.rbHMPOvC-lkp@intel.com/config)
compiler: gcc-14 (Debian 14.2.0-19) 14.2.0
sparse: v0.6.5-rc1
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260320/202603201429.rbHMPOvC-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/202603201429.rbHMPOvC-lkp@intel.com/
sparse warnings: (new ones prefixed by >>)
>> drivers/acpi/apei/ghes_cper.c:391:1: sparse: sparse: symbol 'cxl_cper_fifo' was not declared. Should it be static?
vim +/cxl_cper_fifo +391 drivers/acpi/apei/ghes_cper.c
388
389 /* Room for 8 entries for each of the 4 event log queues */
390 #define CXL_CPER_FIFO_DEPTH 32
> 391 DEFINE_KFIFO(cxl_cper_fifo, struct cxl_cper_work_data, CXL_CPER_FIFO_DEPTH);
392
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply
* Re: [PATCH v7 07/10] x86/vmscape: Use static_call() for predictor flush
From: Pawan Gupta @ 2026-03-20 6:22 UTC (permalink / raw)
To: Peter Zijlstra
Cc: x86, Nikolay Borisov, H. Peter Anvin, Josh Poimboeuf,
David Kaplan, Sean Christopherson, Borislav Petkov, Dave Hansen,
Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko, KP Singh,
Jiri Olsa, David S. Miller, David Laight, Andy Lutomirski,
Thomas Gleixner, Ingo Molnar, David Ahern, Martin KaFai Lau,
Eduard Zingerman, Song Liu, Yonghong Song, John Fastabend,
Stanislav Fomichev, Hao Luo, Paolo Bonzini, Jonathan Corbet,
linux-kernel, kvm, Asit Mallick, Tao Zhang, bpf, netdev,
linux-doc
In-Reply-To: <20260319214409.GL3738786@noisy.programming.kicks-ass.net>
On Thu, Mar 19, 2026 at 10:44:09PM +0100, Peter Zijlstra wrote:
...
> > With _TRAMP, KVM complains:
> >
> > ERROR: modpost: "__SCK__vmscape_predictor_flush" [arch/x86/kvm/kvm.ko] undefined!
>
> Ah, tricky. Yeah, this would need to be solved differenlty. Perhaps wrap
> this in a helper and export that?
bool vmscape_mitigation_enabled(void)
{
return unlikely(static_call_query(vmscape_predictor_flush));
}
EXPORT_SYMBOL_FOR_KVM(vmscape_mitigation_enabled);
This is definitely simpler option, but adds an exported function and an
unnecessary call to it.
> Or use the below little thing and change it to
> EXPORT_STATIC_CALL_FOR_MODULES(foo, "kvm"); or whatnot.
>
> > Probably one option is to somehow make sure that the key can be set to
> > __ro_after_init? I don't see a use case for modifying the static_call() after
> > boot.
>
> So we have __ro_after_init for static_branch, but we'd not done
> it for static_call yet. It shouldn't be terribly difficult, just hasn't
> been done. Not sure this is the moment to do so.
>
>
> ---
> diff --git a/include/linux/static_call.h b/include/linux/static_call.h
> index 78a77a4ae0ea..b610afd1ed55 100644
> --- a/include/linux/static_call.h
> +++ b/include/linux/static_call.h
> @@ -216,6 +216,9 @@ extern long __static_call_return0(void);
> #define EXPORT_STATIC_CALL_GPL(name) \
> EXPORT_SYMBOL_GPL(STATIC_CALL_KEY(name)); \
> EXPORT_SYMBOL_GPL(STATIC_CALL_TRAMP(name))
> +#define EXPORT_STATIC_CALL_FOR_MODULES(name, mods) \
> + EXPORT_SYMBOL_FOR_MODULES(STATIC_CALL_KEY(name), mods); \
> + EXPORT_SYMBOL_FOR_MODULES(STATIC_CALL_TRAMP(name), mods)
>
> /* Leave the key unexported, so modules can't change static call targets: */
> #define EXPORT_STATIC_CALL_TRAMP(name) \
> @@ -276,6 +279,9 @@ extern long __static_call_return0(void);
> #define EXPORT_STATIC_CALL_GPL(name) \
> EXPORT_SYMBOL_GPL(STATIC_CALL_KEY(name)); \
> EXPORT_SYMBOL_GPL(STATIC_CALL_TRAMP(name))
> +#define EXPORT_STATIC_CALL_FOR_MODULES(name, mods) \
> + EXPORT_SYMBOL_FOR_MODULES(STATIC_CALL_KEY(name), mods); \
> + EXPORT_SYMBOL_FOR_MODULES(STATIC_CALL_TRAMP(name), mods)
>
> /* Leave the key unexported, so modules can't change static call targets: */
> #define EXPORT_STATIC_CALL_TRAMP(name) \
> @@ -346,6 +352,8 @@ static inline int static_call_text_reserved(void *start, void *end)
>
> #define EXPORT_STATIC_CALL(name) EXPORT_SYMBOL(STATIC_CALL_KEY(name))
> #define EXPORT_STATIC_CALL_GPL(name) EXPORT_SYMBOL_GPL(STATIC_CALL_KEY(name))
> +#define EXPORT_STATIC_CALL_FOR_MODULES(name, mods) \
> + EXPORT_SYMBOL_FOR_MODULES(STATIC_CALL_KEY(name), mods)
>
> #endif /* CONFIG_HAVE_STATIC_CALL */
This plus extending it to support EXPORT_STATIC_CALL_FOR_KVM() is probably
a better solution. Please let me know which one you prefer.
diff --git a/include/linux/kvm_types.h b/include/linux/kvm_types.h
index a568d8e6f4e8..89c4964c8560 100644
--- a/include/linux/kvm_types.h
+++ b/include/linux/kvm_types.h
@@ -13,6 +13,9 @@
EXPORT_SYMBOL_FOR_MODULES(symbol, __stringify(KVM_SUB_MODULES))
#define EXPORT_SYMBOL_FOR_KVM(symbol) \
EXPORT_SYMBOL_FOR_MODULES(symbol, "kvm," __stringify(KVM_SUB_MODULES))
+#define EXPORT_STATIC_CALL_FOR_KVM(symbol) \
+ EXPORT_STATIC_CALL_FOR_MODULES(symbol ,"kvm," __stringify(KVM_SUB_MODULES))
+
#else
#define EXPORT_SYMBOL_FOR_KVM_INTERNAL(symbol)
/*
@@ -23,6 +26,7 @@
#ifndef EXPORT_SYMBOL_FOR_KVM
#if IS_MODULE(CONFIG_KVM)
#define EXPORT_SYMBOL_FOR_KVM(symbol) EXPORT_SYMBOL_FOR_MODULES(symbol, "kvm")
+#define EXPORT_STATIC_CALL_FOR_KVM(symbol) EXPORT_STATIC_CALL_FOR_MODULES(symbol ,"kvm")
#else
#define EXPORT_SYMBOL_FOR_KVM(symbol)
#endif /* IS_MODULE(CONFIG_KVM) */
diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
index 5f102af4921f..0abdb54f7510 100644
--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -145,7 +145,7 @@ EXPORT_SYMBOL_GPL(cpu_buf_idle_clear);
DEFINE_STATIC_KEY_FALSE(switch_mm_cond_l1d_flush);
DEFINE_STATIC_CALL_NULL(vmscape_predictor_flush, write_ibpb);
-EXPORT_STATIC_CALL_GPL(vmscape_predictor_flush);
+EXPORT_STATIC_CALL_FOR_KVM(vmscape_predictor_flush);
#undef pr_fmt
#define pr_fmt(fmt) "mitigations: " fmt
^ permalink raw reply related
* Re: [PATCH] Docs/mm/damon: document min_nr_regions constraint and rationale
From: Liew Rui Yan @ 2026-03-20 5:41 UTC (permalink / raw)
To: sj; +Cc: aethernet65535, damon, linux-doc, linux-mm
In-Reply-To: <20260320052428.213230-1-aethernet65535@gmail.com>
Hi SeongJae,
I'm sorry for the noise; please ignore my previous reply. I accidentally
sent the commit message instead of my intended message.
What I wanted to ask is regarding tasks 3 and 4 from our earlier plan
[1]: should I wait to start both of them later? Or is it only task 3
that needs to wait until your fix is merged or abandoned?
Also, I'm preparing to post an RFC patch for 'damon_hot_score'
optimization soon. It aims to provide a significant performance
improvement.
[1] https://lore.kernel.org/damon/20260319151528.86490-1-sj@kernel.org/T/#t
Best regards,
Rui Yan
^ permalink raw reply
* Re: [PATCH] Docs/mm/damon: document min_nr_regions constraint and rationale
From: Liew Rui Yan @ 2026-03-20 5:37 UTC (permalink / raw)
To: sj; +Cc: aethernet65535, damon, linux-doc, linux-mm
In-Reply-To: <20260320052428.213230-1-aethernet65535@gmail.com>
The current DAMON implementation requires 'min_nr_regions' to be at
least 3. However, this constraint is not explicitly documented in the
admin-guide documents, nor is its design rationale explained in the
design document.
Add a section in design.rst to explain the rationale: the virtual
address space monitoring design needs to handle at least three regions
to accommodate two large unmapped areas. While this is specific to
'vaddr', DAMON currently enforces it across all operation sets for
consistency.
Also update reclaim.rst and lru_sort.rst by adding cross-references to
this constraint at the end of their respective parameter description or
usage sections, ensuring users are aware of the lower bound.
This change is motivated from a recent discussion [1].
[1] https://lore.kernel.org/damon/20260319151528.86490-1-sj@kernel.org/T/#t
^ permalink raw reply
* [PATCH] Docs/mm/damon: document min_nr_regions constraint and rationale
From: Liew Rui Yan @ 2026-03-20 5:24 UTC (permalink / raw)
To: sj; +Cc: linux-mm, damon, linux-doc, Liew Rui Yan
The current DAMON implementation requires 'min_nr_regions' to be at
least 3. However, this constraint is not explicitly documented in the
admin-guide documents, nor is its design rationale explained in the
design document.
Add a section in design.rst to explain the rationale: the virtual
address space monitoring design needs to handle at least three regions
to accommodate two large unmapped areas. While this is specific to
'vaddr', DAMON currently enforces it across all operation sets for
consistency.
Also update reclaim.rst and lru_sort.rst by adding cross-references to
this constraint within their respective 'min_nr_regions' parameter
description sections, ensuring users are aware of the lower bound.
This change is motivated from a recent discussion [1].
[1] https://lore.kernel.org/damon/20260319151528.86490-1-sj@kernel.org/T/#t
Signed-off-by: Liew Rui Yan <aethernet65535@gmail.com>
---
Documentation/admin-guide/mm/damon/lru_sort.rst | 4 ++++
Documentation/admin-guide/mm/damon/reclaim.rst | 4 ++++
Documentation/mm/damon/design.rst | 7 +++++++
3 files changed, 15 insertions(+)
diff --git a/Documentation/admin-guide/mm/damon/lru_sort.rst b/Documentation/admin-guide/mm/damon/lru_sort.rst
index 20a8378d5a94..3d08baf9802c 100644
--- a/Documentation/admin-guide/mm/damon/lru_sort.rst
+++ b/Documentation/admin-guide/mm/damon/lru_sort.rst
@@ -221,6 +221,10 @@ But, setting this too high could result in increased monitoring overhead.
Please refer to the DAMON documentation (:doc:`usage`) for more detail. 10 by
default.
+Note that this must be 3 or higher. Please refer to the :ref:`Monitoring
+<damon_design_monitoring>` section of the design document for the rationale
+behind this lower bound.
+
max_nr_regions
--------------
diff --git a/Documentation/admin-guide/mm/damon/reclaim.rst b/Documentation/admin-guide/mm/damon/reclaim.rst
index 8eba3da8dcee..153bf42645dd 100644
--- a/Documentation/admin-guide/mm/damon/reclaim.rst
+++ b/Documentation/admin-guide/mm/damon/reclaim.rst
@@ -204,6 +204,10 @@ monitoring. This can be used to set lower-bound of the monitoring quality.
But, setting this too high could result in increased monitoring overhead.
Please refer to the DAMON documentation (:doc:`usage`) for more detail.
+Note that this must be 3 or higher. Please refer to the :ref:`Monitoring
+<damon_design_monitoring>` section of the design document for the rationale
+behind this lower bound.
+
max_nr_regions
--------------
diff --git a/Documentation/mm/damon/design.rst b/Documentation/mm/damon/design.rst
index dd64f5d7f319..68a25e07203c 100644
--- a/Documentation/mm/damon/design.rst
+++ b/Documentation/mm/damon/design.rst
@@ -165,6 +165,13 @@ monitoring attributes, ``sampling interval``, ``aggregation interval``,
``update interval``, ``minimum number of regions``, and ``maximum number of
regions``.
+Note that ``minimum number of regions`` must be 3 or higher. This is because the
+virtual address space monitoring is designed to handle at least three regions to
+accommodate two large unmapped areas commonly found in normal virtual address
+spaces. While this restriction might not be strictly necessary for other
+operation sets like ``paddr``, it is currently enforced across all DAMON
+operations for consistency.
+
To know how user-space can set the attributes via :ref:`DAMON sysfs interface
<sysfs_interface>`, refer to :ref:`monitoring_attrs <sysfs_monitoring_attrs>`
part of the documentation.
--
2.53.0
^ permalink raw reply related
* [PATCH v14 1/2] rust: gpu: Add GPU buddy allocator bindings
From: Joel Fernandes @ 2026-03-20 4:57 UTC (permalink / raw)
To: linux-kernel
Cc: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
Danilo Krummrich, Dave Airlie, Daniel Almeida, Koen Koning,
dri-devel, rust-for-linux, Nikola Djukic, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
Jonathan Corbet, Alex Deucher, Christian König, Jani Nikula,
Joonas Lahtinen, Rodrigo Vivi, Tvrtko Ursulin, Huang Rui,
Matthew Auld, Matthew Brost, Lucas De Marchi,
Thomas Hellström, Helge Deller, Alex Gaynor, Boqun Feng,
John Hubbard, Alistair Popple, Timur Tabi, Edwin Peer,
Alexandre Courbot, Andrea Righi, Andy Ritger, Zhi Wang,
Balbir Singh, Philipp Stanner, Elle Rhumsaa, alexeyi,
Eliot Courtney, joel, linux-doc, amd-gfx, intel-gfx, intel-xe,
linux-fbdev, Joel Fernandes
In-Reply-To: <20260320045711.43494-1-joelagnelf@nvidia.com>
Add safe Rust abstractions over the Linux kernel's GPU buddy
allocator for physical memory management. The GPU buddy allocator
implements a binary buddy system useful for GPU physical memory
allocation. nova-core will use it for physical memory allocation.
Cc: Nikola Djukic <ndjukic@nvidia.com>
Signed-off-by: Joel Fernandes <joelagnelf@nvidia.com>
---
MAINTAINERS | 6 +
rust/bindings/bindings_helper.h | 11 +
rust/helpers/gpu.c | 23 ++
rust/helpers/helpers.c | 1 +
rust/kernel/gpu.rs | 6 +
rust/kernel/gpu/buddy.rs | 613 ++++++++++++++++++++++++++++++++
rust/kernel/lib.rs | 2 +
7 files changed, 662 insertions(+)
create mode 100644 rust/helpers/gpu.c
create mode 100644 rust/kernel/gpu.rs
create mode 100644 rust/kernel/gpu/buddy.rs
diff --git a/MAINTAINERS b/MAINTAINERS
index e847099efcc2..cd9505d3be60 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8531,7 +8531,10 @@ T: git https://gitlab.freedesktop.org/drm/rust/kernel.git
F: drivers/gpu/drm/nova/
F: drivers/gpu/drm/tyr/
F: drivers/gpu/nova-core/
+F: rust/helpers/gpu.c
F: rust/kernel/drm/
+F: rust/kernel/gpu.rs
+F: rust/kernel/gpu/
DRM DRIVERS FOR ALLWINNER A10
M: Chen-Yu Tsai <wens@kernel.org>
@@ -8952,6 +8955,9 @@ F: drivers/gpu/drm/drm_buddy.c
F: drivers/gpu/tests/gpu_buddy_test.c
F: include/drm/drm_buddy.h
F: include/linux/gpu_buddy.h
+F: rust/helpers/gpu.c
+F: rust/kernel/gpu.rs
+F: rust/kernel/gpu/
DRM AUTOMATED TESTING
M: Helen Koike <helen.fornazier@gmail.com>
diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h
index 083cc44aa952..dbb765a9fdbd 100644
--- a/rust/bindings/bindings_helper.h
+++ b/rust/bindings/bindings_helper.h
@@ -29,6 +29,7 @@
#include <linux/hrtimer_types.h>
#include <linux/acpi.h>
+#include <linux/gpu_buddy.h>
#include <drm/drm_device.h>
#include <drm/drm_drv.h>
#include <drm/drm_file.h>
@@ -146,6 +147,16 @@ const vm_flags_t RUST_CONST_HELPER_VM_MIXEDMAP = VM_MIXEDMAP;
const vm_flags_t RUST_CONST_HELPER_VM_HUGEPAGE = VM_HUGEPAGE;
const vm_flags_t RUST_CONST_HELPER_VM_NOHUGEPAGE = VM_NOHUGEPAGE;
+#if IS_ENABLED(CONFIG_GPU_BUDDY)
+const unsigned long RUST_CONST_HELPER_GPU_BUDDY_RANGE_ALLOCATION = GPU_BUDDY_RANGE_ALLOCATION;
+const unsigned long RUST_CONST_HELPER_GPU_BUDDY_TOPDOWN_ALLOCATION = GPU_BUDDY_TOPDOWN_ALLOCATION;
+const unsigned long RUST_CONST_HELPER_GPU_BUDDY_CONTIGUOUS_ALLOCATION =
+ GPU_BUDDY_CONTIGUOUS_ALLOCATION;
+const unsigned long RUST_CONST_HELPER_GPU_BUDDY_CLEAR_ALLOCATION = GPU_BUDDY_CLEAR_ALLOCATION;
+const unsigned long RUST_CONST_HELPER_GPU_BUDDY_CLEARED = GPU_BUDDY_CLEARED;
+const unsigned long RUST_CONST_HELPER_GPU_BUDDY_TRIM_DISABLE = GPU_BUDDY_TRIM_DISABLE;
+#endif
+
#if IS_ENABLED(CONFIG_ANDROID_BINDER_IPC_RUST)
#include "../../drivers/android/binder/rust_binder.h"
#include "../../drivers/android/binder/rust_binder_events.h"
diff --git a/rust/helpers/gpu.c b/rust/helpers/gpu.c
new file mode 100644
index 000000000000..38b1a4e6bef8
--- /dev/null
+++ b/rust/helpers/gpu.c
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/gpu_buddy.h>
+
+#ifdef CONFIG_GPU_BUDDY
+
+__rust_helper u64 rust_helper_gpu_buddy_block_offset(const struct gpu_buddy_block *block)
+{
+ return gpu_buddy_block_offset(block);
+}
+
+__rust_helper unsigned int rust_helper_gpu_buddy_block_order(struct gpu_buddy_block *block)
+{
+ return gpu_buddy_block_order(block);
+}
+
+__rust_helper u64 rust_helper_gpu_buddy_block_size(struct gpu_buddy *mm,
+ struct gpu_buddy_block *block)
+{
+ return gpu_buddy_block_size(mm, block);
+}
+
+#endif /* CONFIG_GPU_BUDDY */
diff --git a/rust/helpers/helpers.c b/rust/helpers/helpers.c
index 724fcb8240ac..a53929ce52a3 100644
--- a/rust/helpers/helpers.c
+++ b/rust/helpers/helpers.c
@@ -32,6 +32,7 @@
#include "err.c"
#include "irq.c"
#include "fs.c"
+#include "gpu.c"
#include "io.c"
#include "jump_label.c"
#include "kunit.c"
diff --git a/rust/kernel/gpu.rs b/rust/kernel/gpu.rs
new file mode 100644
index 000000000000..1dc5d0c8c09d
--- /dev/null
+++ b/rust/kernel/gpu.rs
@@ -0,0 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! GPU subsystem abstractions.
+
+#[cfg(CONFIG_GPU_BUDDY = "y")]
+pub mod buddy;
diff --git a/rust/kernel/gpu/buddy.rs b/rust/kernel/gpu/buddy.rs
new file mode 100644
index 000000000000..fdf1fcc2dcee
--- /dev/null
+++ b/rust/kernel/gpu/buddy.rs
@@ -0,0 +1,613 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! GPU buddy allocator bindings.
+//!
+//! C header: [`include/linux/gpu_buddy.h`](srctree/include/linux/gpu_buddy.h)
+//!
+//! This module provides Rust abstractions over the Linux kernel's GPU buddy
+//! allocator, which implements a binary buddy memory allocator.
+//!
+//! The buddy allocator manages a contiguous address space and allocates blocks
+//! in power-of-two sizes, useful for GPU physical memory management.
+//!
+//! # Examples
+//!
+//! Create a buddy allocator and perform a basic range allocation:
+//!
+//! ```
+//! use kernel::{
+//! gpu::buddy::{
+//! GpuBuddy,
+//! GpuBuddyAllocFlags,
+//! GpuBuddyAllocMode,
+//! GpuBuddyParams, //
+//! },
+//! prelude::*,
+//! ptr::Alignment,
+//! sizes::*, //
+//! };
+//!
+//! // Create a 1GB buddy allocator with 4KB minimum chunk size.
+//! let buddy = GpuBuddy::new(GpuBuddyParams {
+//! base_offset: 0,
+//! size: SZ_1G as u64,
+//! chunk_size: Alignment::new::<SZ_4K>(),
+//! })?;
+//!
+//! assert_eq!(buddy.size(), SZ_1G as u64);
+//! assert_eq!(buddy.chunk_size(), Alignment::new::<SZ_4K>());
+//! let initial_free = buddy.avail();
+//!
+//! // Allocate 16MB. Block lands at the top of the address range.
+//! let allocated = KBox::pin_init(
+//! buddy.alloc_blocks(
+//! GpuBuddyAllocMode::Simple,
+//! SZ_16M as u64,
+//! Alignment::new::<SZ_16M>(),
+//! GpuBuddyAllocFlags::default(),
+//! ),
+//! GFP_KERNEL,
+//! )?;
+//! assert_eq!(buddy.avail(), initial_free - SZ_16M as u64);
+//!
+//! let block = allocated.iter().next().expect("expected one block");
+//! assert_eq!(block.offset(), (SZ_1G - SZ_16M) as u64);
+//! assert_eq!(block.order(), 12); // 2^12 pages = 16MB
+//! assert_eq!(block.size(), SZ_16M as u64);
+//! assert_eq!(allocated.iter().count(), 1);
+//!
+//! // Dropping the allocation returns the range to the buddy allocator.
+//! drop(allocated);
+//! assert_eq!(buddy.avail(), initial_free);
+//! # Ok::<(), Error>(())
+//! ```
+//!
+//! Top-down allocation allocates from the highest addresses:
+//!
+//! ```
+//! # use kernel::{
+//! # gpu::buddy::{GpuBuddy, GpuBuddyAllocMode, GpuBuddyAllocFlags, GpuBuddyParams},
+//! # prelude::*,
+//! # ptr::Alignment,
+//! # sizes::*, //
+//! # };
+//! # let buddy = GpuBuddy::new(GpuBuddyParams {
+//! # base_offset: 0,
+//! # size: SZ_1G as u64,
+//! # chunk_size: Alignment::new::<SZ_4K>(),
+//! # })?;
+//! # let initial_free = buddy.avail();
+//! let topdown = KBox::pin_init(
+//! buddy.alloc_blocks(
+//! GpuBuddyAllocMode::TopDown,
+//! SZ_16M as u64,
+//! Alignment::new::<SZ_16M>(),
+//! GpuBuddyAllocFlags::default(),
+//! ),
+//! GFP_KERNEL,
+//! )?;
+//! assert_eq!(buddy.avail(), initial_free - SZ_16M as u64);
+//!
+//! let block = topdown.iter().next().expect("expected one block");
+//! assert_eq!(block.offset(), (SZ_1G - SZ_16M) as u64);
+//! assert_eq!(block.order(), 12);
+//! assert_eq!(block.size(), SZ_16M as u64);
+//!
+//! // Dropping the allocation returns the range to the buddy allocator.
+//! drop(topdown);
+//! assert_eq!(buddy.avail(), initial_free);
+//! # Ok::<(), Error>(())
+//! ```
+//!
+//! Non-contiguous allocation can fill fragmented memory by returning multiple
+//! blocks:
+//!
+//! ```
+//! # use kernel::{
+//! # gpu::buddy::{
+//! # GpuBuddy, GpuBuddyAllocFlags, GpuBuddyAllocMode, GpuBuddyParams,
+//! # },
+//! # prelude::*,
+//! # ptr::Alignment,
+//! # sizes::*, //
+//! # };
+//! # let buddy = GpuBuddy::new(GpuBuddyParams {
+//! # base_offset: 0,
+//! # size: SZ_1G as u64,
+//! # chunk_size: Alignment::new::<SZ_4K>(),
+//! # })?;
+//! # let initial_free = buddy.avail();
+//! // Create fragmentation by allocating 4MB blocks at [0,4M) and [8M,12M).
+//! let frag1 = KBox::pin_init(
+//! buddy.alloc_blocks(
+//! GpuBuddyAllocMode::Range(0..SZ_4M as u64),
+//! SZ_4M as u64,
+//! Alignment::new::<SZ_4M>(),
+//! GpuBuddyAllocFlags::default(),
+//! ),
+//! GFP_KERNEL,
+//! )?;
+//! assert_eq!(buddy.avail(), initial_free - SZ_4M as u64);
+//!
+//! let frag2 = KBox::pin_init(
+//! buddy.alloc_blocks(
+//! GpuBuddyAllocMode::Range(SZ_8M as u64..(SZ_8M + SZ_4M) as u64),
+//! SZ_4M as u64,
+//! Alignment::new::<SZ_4M>(),
+//! GpuBuddyAllocFlags::default(),
+//! ),
+//! GFP_KERNEL,
+//! )?;
+//! assert_eq!(buddy.avail(), initial_free - SZ_8M as u64);
+//!
+//! // Allocate 8MB, this returns 2 blocks from the holes.
+//! let fragmented = KBox::pin_init(
+//! buddy.alloc_blocks(
+//! GpuBuddyAllocMode::Range(0..SZ_16M as u64),
+//! SZ_8M as u64,
+//! Alignment::new::<SZ_4M>(),
+//! GpuBuddyAllocFlags::default(),
+//! ),
+//! GFP_KERNEL,
+//! )?;
+//! assert_eq!(buddy.avail(), initial_free - SZ_16M as u64);
+//!
+//! let (mut count, mut total) = (0u32, 0u64);
+//! for block in fragmented.iter() {
+//! assert_eq!(block.size(), SZ_4M as u64);
+//! total += block.size();
+//! count += 1;
+//! }
+//! assert_eq!(total, SZ_8M as u64);
+//! assert_eq!(count, 2);
+//! # Ok::<(), Error>(())
+//! ```
+//!
+//! Contiguous allocation fails when only fragmented space is available:
+//!
+//! ```
+//! # use kernel::{
+//! # gpu::buddy::{
+//! # GpuBuddy, GpuBuddyAllocFlag, GpuBuddyAllocFlags, GpuBuddyAllocMode, GpuBuddyParams,
+//! # },
+//! # prelude::*,
+//! # ptr::Alignment,
+//! # sizes::*, //
+//! # };
+//! // Create a small 16MB buddy allocator with fragmented memory.
+//! let small = GpuBuddy::new(GpuBuddyParams {
+//! base_offset: 0,
+//! size: SZ_16M as u64,
+//! chunk_size: Alignment::new::<SZ_4K>(),
+//! })?;
+//!
+//! let _hole1 = KBox::pin_init(
+//! small.alloc_blocks(
+//! GpuBuddyAllocMode::Range(0..SZ_4M as u64),
+//! SZ_4M as u64,
+//! Alignment::new::<SZ_4M>(),
+//! GpuBuddyAllocFlags::default(),
+//! ),
+//! GFP_KERNEL,
+//! )?;
+//!
+//! let _hole2 = KBox::pin_init(
+//! small.alloc_blocks(
+//! GpuBuddyAllocMode::Range(SZ_8M as u64..(SZ_8M + SZ_4M) as u64),
+//! SZ_4M as u64,
+//! Alignment::new::<SZ_4M>(),
+//! GpuBuddyAllocFlags::default(),
+//! ),
+//! GFP_KERNEL,
+//! )?;
+//!
+//! // 8MB contiguous should fail, only two non-contiguous 4MB holes exist.
+//! let result = KBox::pin_init(
+//! small.alloc_blocks(
+//! GpuBuddyAllocMode::Simple,
+//! SZ_8M as u64,
+//! Alignment::new::<SZ_4M>(),
+//! GpuBuddyAllocFlag::Contiguous,
+//! ),
+//! GFP_KERNEL,
+//! );
+//! assert!(result.is_err());
+//! # Ok::<(), Error>(())
+//! ```
+
+use core::ops::Range;
+
+use crate::{
+ bindings,
+ clist_create,
+ error::to_result,
+ interop::list::CListHead,
+ new_mutex,
+ prelude::*,
+ ptr::Alignment,
+ sync::{
+ lock::mutex::MutexGuard,
+ Arc,
+ Mutex, //
+ },
+ types::Opaque, //
+};
+
+/// Allocation mode for the GPU buddy allocator.
+///
+/// The mode determines the primary allocation strategy. Modes are mutually
+/// exclusive: an allocation is either simple, range-constrained, or top-down.
+///
+/// Orthogonal modifier flags (e.g., contiguous, clear) are specified separately
+/// via [`GpuBuddyAllocFlags`].
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub enum GpuBuddyAllocMode {
+ /// Simple allocation without constraints.
+ Simple,
+ /// Range-based allocation within the given address range.
+ Range(Range<u64>),
+ /// Allocate from top of address space downward.
+ TopDown,
+}
+
+impl GpuBuddyAllocMode {
+ // Returns the C flags corresponding to the allocation mode.
+ fn as_flags(&self) -> usize {
+ match self {
+ Self::Simple => 0,
+ Self::Range(_) => bindings::GPU_BUDDY_RANGE_ALLOCATION,
+ Self::TopDown => bindings::GPU_BUDDY_TOPDOWN_ALLOCATION,
+ }
+ }
+
+ // Extracts the range start/end, defaulting to `(0, 0)` for non-range modes.
+ fn range(&self) -> (u64, u64) {
+ match self {
+ Self::Range(range) => (range.start, range.end),
+ _ => (0, 0),
+ }
+ }
+}
+
+crate::impl_flags!(
+ /// Modifier flags for GPU buddy allocation.
+ ///
+ /// These flags can be combined with any [`GpuBuddyAllocMode`] to control
+ /// additional allocation behavior.
+ #[derive(Clone, Copy, Default, PartialEq, Eq)]
+ pub struct GpuBuddyAllocFlags(usize);
+
+ /// Individual modifier flag for GPU buddy allocation.
+ #[derive(Clone, Copy, PartialEq, Eq)]
+ pub enum GpuBuddyAllocFlag {
+ /// Allocate physically contiguous blocks.
+ Contiguous = bindings::GPU_BUDDY_CONTIGUOUS_ALLOCATION,
+
+ /// Request allocation from cleared (zeroed) memory.
+ Clear = bindings::GPU_BUDDY_CLEAR_ALLOCATION,
+
+ /// Disable trimming of partially used blocks.
+ TrimDisable = bindings::GPU_BUDDY_TRIM_DISABLE,
+ }
+);
+
+/// Parameters for creating a GPU buddy allocator.
+pub struct GpuBuddyParams {
+ /// Base offset (in bytes) where the managed memory region starts.
+ /// Allocations will be offset by this value.
+ pub base_offset: u64,
+ /// Total size (in bytes) of the address space managed by the allocator.
+ pub size: u64,
+ /// Minimum allocation unit / chunk size, must be >= 4KB.
+ pub chunk_size: Alignment,
+}
+
+/// Inner structure holding the actual buddy allocator.
+///
+/// # Synchronization
+///
+/// The C `gpu_buddy` API requires synchronization (see `include/linux/gpu_buddy.h`).
+/// Internal locking ensures all allocator and free operations are properly
+/// synchronized, preventing races between concurrent allocations and the
+/// freeing that occurs when [`AllocatedBlocks`] is dropped.
+///
+/// # Invariants
+///
+/// The inner [`Opaque`] contains an initialized buddy allocator.
+#[pin_data(PinnedDrop)]
+struct GpuBuddyInner {
+ #[pin]
+ inner: Opaque<bindings::gpu_buddy>,
+
+ // TODO: Replace `Mutex<()>` with `Mutex<Opaque<..>>` once `Mutex::new()`
+ // accepts `impl PinInit<T>`.
+ #[pin]
+ lock: Mutex<()>,
+ /// Cached creation parameters (do not change after init).
+ params: GpuBuddyParams,
+}
+
+impl GpuBuddyInner {
+ /// Create a pin-initializer for the buddy allocator.
+ fn new(params: GpuBuddyParams) -> impl PinInit<Self, Error> {
+ let size = params.size;
+ let chunk_size = params.chunk_size;
+
+ // INVARIANT: `gpu_buddy_init` returns 0 on success, at which point the
+ // `gpu_buddy` structure is initialized and ready for use with all
+ // `gpu_buddy_*` APIs. `try_pin_init!` only completes if all fields succeed,
+ // so the invariant holds when construction finishes.
+ try_pin_init!(Self {
+ inner <- Opaque::try_ffi_init(|ptr| {
+ // SAFETY: `ptr` points to valid uninitialized memory from the pin-init
+ // infrastructure. `gpu_buddy_init` will initialize the structure.
+ to_result(unsafe { bindings::gpu_buddy_init(ptr, size, chunk_size.as_usize() as u64) })
+ }),
+ lock <- new_mutex!(()),
+ params,
+ })
+ }
+
+ /// Lock the mutex and return a guard for accessing the allocator.
+ fn lock(&self) -> GpuBuddyGuard<'_> {
+ GpuBuddyGuard {
+ inner: self,
+ _guard: self.lock.lock(),
+ }
+ }
+}
+
+#[pinned_drop]
+impl PinnedDrop for GpuBuddyInner {
+ fn drop(self: Pin<&mut Self>) {
+ let guard = self.lock();
+
+ // SAFETY: Per the type invariant, `inner` contains an initialized
+ // allocator. `guard` provides exclusive access.
+ unsafe {
+ bindings::gpu_buddy_fini(guard.as_raw());
+ }
+ }
+}
+
+// SAFETY: `GpuBuddyInner` can be sent between threads.
+unsafe impl Send for GpuBuddyInner {}
+
+// SAFETY: `GpuBuddyInner` is `Sync` because `GpuBuddyInner::lock`
+// serializes all access to the C allocator, preventing data races.
+unsafe impl Sync for GpuBuddyInner {}
+
+// Guard that proves the lock is held, enabling access to the allocator.
+// The `_guard` holds the lock for the duration of this guard's lifetime.
+struct GpuBuddyGuard<'a> {
+ inner: &'a GpuBuddyInner,
+ _guard: MutexGuard<'a, ()>,
+}
+
+impl GpuBuddyGuard<'_> {
+ /// Get a raw pointer to the underlying C `gpu_buddy` structure.
+ fn as_raw(&self) -> *mut bindings::gpu_buddy {
+ self.inner.inner.get()
+ }
+}
+
+/// GPU buddy allocator instance.
+///
+/// This structure wraps the C `gpu_buddy` allocator using reference counting.
+/// The allocator is automatically cleaned up when all references are dropped.
+///
+/// Refer to the module-level documentation for usage examples.
+pub struct GpuBuddy(Arc<GpuBuddyInner>);
+
+impl GpuBuddy {
+ /// Create a new buddy allocator.
+ ///
+ /// Creates a buddy allocator that manages a contiguous address space of the given
+ /// size, with the specified minimum allocation unit (chunk_size must be at least 4KB).
+ pub fn new(params: GpuBuddyParams) -> Result<Self> {
+ Arc::pin_init(GpuBuddyInner::new(params), GFP_KERNEL).map(Self)
+ }
+
+ /// Get the base offset for allocations.
+ pub fn base_offset(&self) -> u64 {
+ self.0.params.base_offset
+ }
+
+ /// Get the chunk size (minimum allocation unit).
+ pub fn chunk_size(&self) -> Alignment {
+ self.0.params.chunk_size
+ }
+
+ /// Get the total managed size.
+ pub fn size(&self) -> u64 {
+ self.0.params.size
+ }
+
+ /// Get the available (free) memory in bytes.
+ pub fn avail(&self) -> u64 {
+ let guard = self.0.lock();
+
+ // SAFETY: Per the type invariant, `inner` contains an initialized allocator.
+ // `guard` provides exclusive access.
+ unsafe { (*guard.as_raw()).avail }
+ }
+
+ /// Allocate blocks from the buddy allocator.
+ ///
+ /// Returns a pin-initializer for [`AllocatedBlocks`].
+ pub fn alloc_blocks(
+ &self,
+ mode: GpuBuddyAllocMode,
+ size: u64,
+ min_block_size: Alignment,
+ flags: impl Into<GpuBuddyAllocFlags>,
+ ) -> impl PinInit<AllocatedBlocks, Error> {
+ let buddy_arc = Arc::clone(&self.0);
+ let (start, end) = mode.range();
+ let mode_flags = mode.as_flags();
+ let modifier_flags = flags.into();
+
+ // Create pin-initializer that initializes list and allocates blocks.
+ try_pin_init!(AllocatedBlocks {
+ buddy: buddy_arc,
+ list <- CListHead::new(),
+ _: {
+ // Reject zero-sized or inverted ranges.
+ if let GpuBuddyAllocMode::Range(range) = &mode {
+ if range.is_empty() {
+ Err::<(), Error>(EINVAL)?;
+ }
+ }
+
+ // Lock while allocating to serialize with concurrent frees.
+ let guard = buddy.lock();
+
+ // SAFETY: Per the type invariant, `inner` contains an initialized
+ // allocator. `guard` provides exclusive access.
+ to_result(unsafe {
+ bindings::gpu_buddy_alloc_blocks(
+ guard.as_raw(),
+ start,
+ end,
+ size,
+ min_block_size.as_usize() as u64,
+ list.as_raw(),
+ mode_flags | usize::from(modifier_flags),
+ )
+ })?
+ }
+ })
+ }
+}
+
+/// Allocated blocks from the buddy allocator with automatic cleanup.
+///
+/// This structure owns a list of allocated blocks and ensures they are
+/// automatically freed when dropped. Use `iter()` to iterate over all
+/// allocated blocks.
+///
+/// # Invariants
+///
+/// - `list` is an initialized, valid list head containing allocated blocks.
+#[pin_data(PinnedDrop)]
+pub struct AllocatedBlocks {
+ #[pin]
+ list: CListHead,
+ buddy: Arc<GpuBuddyInner>,
+}
+
+impl AllocatedBlocks {
+ /// Check if the block list is empty.
+ pub fn is_empty(&self) -> bool {
+ // An empty list head points to itself.
+ !self.list.is_linked()
+ }
+
+ /// Iterate over allocated blocks.
+ ///
+ /// Returns an iterator yielding [`AllocatedBlock`] values. Each [`AllocatedBlock`]
+ /// borrows `self` and is only valid for the duration of that borrow.
+ pub fn iter(&self) -> impl Iterator<Item = AllocatedBlock<'_>> + '_ {
+ let head = self.list.as_raw();
+ // SAFETY: Per the type invariant, `list` is an initialized sentinel `list_head`
+ // and is not concurrently modified (we hold a `&self` borrow). The list contains
+ // `gpu_buddy_block` items linked via `__bindgen_anon_1.link`. `Block` is
+ // `#[repr(transparent)]` over `gpu_buddy_block`.
+ let clist = unsafe {
+ clist_create!(
+ head,
+ Block,
+ bindings::gpu_buddy_block,
+ __bindgen_anon_1.link
+ )
+ };
+
+ clist
+ .iter()
+ .map(|this| AllocatedBlock { this, blocks: self })
+ }
+}
+
+#[pinned_drop]
+impl PinnedDrop for AllocatedBlocks {
+ fn drop(self: Pin<&mut Self>) {
+ let guard = self.buddy.lock();
+
+ // SAFETY:
+ // - list is valid per the type's invariants.
+ // - guard provides exclusive access to the allocator.
+ unsafe {
+ bindings::gpu_buddy_free_list(guard.as_raw(), self.list.as_raw(), 0);
+ }
+ }
+}
+
+/// A GPU buddy block.
+///
+/// Transparent wrapper over C `gpu_buddy_block` structure. This type is returned
+/// as references during iteration over [`AllocatedBlocks`].
+///
+/// # Invariants
+///
+/// The inner [`Opaque`] contains a valid, allocated `gpu_buddy_block`.
+#[repr(transparent)]
+struct Block(Opaque<bindings::gpu_buddy_block>);
+
+impl Block {
+ /// Get a raw pointer to the underlying C block.
+ fn as_raw(&self) -> *mut bindings::gpu_buddy_block {
+ self.0.get()
+ }
+
+ /// Get the block's raw offset in the buddy address space (without base offset).
+ fn offset(&self) -> u64 {
+ // SAFETY: `self.as_raw()` is valid per the type's invariants.
+ unsafe { bindings::gpu_buddy_block_offset(self.as_raw()) }
+ }
+
+ /// Get the block order.
+ fn order(&self) -> u32 {
+ // SAFETY: `self.as_raw()` is valid per the type's invariants.
+ unsafe { bindings::gpu_buddy_block_order(self.as_raw()) }
+ }
+}
+
+// SAFETY: `Block` is a wrapper around `gpu_buddy_block` which can be
+// sent across threads safely.
+unsafe impl Send for Block {}
+
+// SAFETY: `Block` is only accessed through shared references after
+// allocation, and thus safe to access concurrently across threads.
+unsafe impl Sync for Block {}
+
+/// A buddy block paired with its owning [`AllocatedBlocks`] context.
+///
+/// Unlike a raw block, which only knows its offset within the buddy address
+/// space, an [`AllocatedBlock`] also has access to the allocator's `base_offset`
+/// and `chunk_size`, enabling it to compute absolute offsets and byte sizes.
+///
+/// Returned by [`AllocatedBlocks::iter()`].
+pub struct AllocatedBlock<'a> {
+ this: &'a Block,
+ blocks: &'a AllocatedBlocks,
+}
+
+impl AllocatedBlock<'_> {
+ /// Get the block's offset in the address space.
+ ///
+ /// Returns the absolute offset including the allocator's base offset.
+ /// This is the actual address to use for accessing the allocated memory.
+ pub fn offset(&self) -> u64 {
+ self.blocks.buddy.params.base_offset + self.this.offset()
+ }
+
+ /// Get the block order (size = chunk_size << order).
+ pub fn order(&self) -> u32 {
+ self.this.order()
+ }
+
+ /// Get the block's size in bytes.
+ pub fn size(&self) -> u64 {
+ (self.blocks.buddy.params.chunk_size.as_usize() as u64) << self.this.order()
+ }
+}
diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
index bdcf632050ee..2652933e585f 100644
--- a/rust/kernel/lib.rs
+++ b/rust/kernel/lib.rs
@@ -102,6 +102,8 @@
pub mod firmware;
pub mod fmt;
pub mod fs;
+#[cfg(CONFIG_GPU_BUDDY = "y")]
+pub mod gpu;
#[cfg(CONFIG_I2C = "y")]
pub mod i2c;
pub mod id_pool;
--
2.34.1
^ permalink raw reply related
* [PATCH v14 2/2] MAINTAINERS: gpu: buddy: Update reviewer
From: Joel Fernandes @ 2026-03-20 4:57 UTC (permalink / raw)
To: linux-kernel
Cc: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
Danilo Krummrich, Dave Airlie, Daniel Almeida, Koen Koning,
dri-devel, rust-for-linux, Nikola Djukic, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
Jonathan Corbet, Alex Deucher, Christian König, Jani Nikula,
Joonas Lahtinen, Rodrigo Vivi, Tvrtko Ursulin, Huang Rui,
Matthew Auld, Matthew Brost, Lucas De Marchi,
Thomas Hellström, Helge Deller, Alex Gaynor, Boqun Feng,
John Hubbard, Alistair Popple, Timur Tabi, Edwin Peer,
Alexandre Courbot, Andrea Righi, Andy Ritger, Zhi Wang,
Balbir Singh, Philipp Stanner, Elle Rhumsaa, alexeyi,
Eliot Courtney, joel, linux-doc, amd-gfx, intel-gfx, intel-xe,
linux-fbdev, Joel Fernandes
In-Reply-To: <20260320045711.43494-1-joelagnelf@nvidia.com>
Christian Koenig mentioned he'd like to step down from the reviewer
role for the GPU buddy allocator. Joel Fernandes is stepping in as
reviewer with agreement from Matthew Auld and Arun Pravin.
Signed-off-by: Joel Fernandes <joelagnelf@nvidia.com>
---
MAINTAINERS | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/MAINTAINERS b/MAINTAINERS
index cd9505d3be60..3353cbf98be1 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8946,7 +8946,7 @@ F: include/drm/ttm/
GPU BUDDY ALLOCATOR
M: Matthew Auld <matthew.auld@intel.com>
M: Arun Pravin <arunpravin.paneerselvam@amd.com>
-R: Christian Koenig <christian.koenig@amd.com>
+R: Joel Fernandes <joelagnelf@nvidia.com>
L: dri-devel@lists.freedesktop.org
S: Maintained
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
--
2.34.1
^ permalink raw reply related
* [PATCH v14 0/2] Rust GPU buddy allocator bindings
From: Joel Fernandes @ 2026-03-20 4:57 UTC (permalink / raw)
To: linux-kernel
Cc: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
Danilo Krummrich, Dave Airlie, Daniel Almeida, Koen Koning,
dri-devel, rust-for-linux, Nikola Djukic, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
Jonathan Corbet, Alex Deucher, Christian König, Jani Nikula,
Joonas Lahtinen, Rodrigo Vivi, Tvrtko Ursulin, Huang Rui,
Matthew Auld, Matthew Brost, Lucas De Marchi,
Thomas Hellström, Helge Deller, Alex Gaynor, Boqun Feng,
John Hubbard, Alistair Popple, Timur Tabi, Edwin Peer,
Alexandre Courbot, Andrea Righi, Andy Ritger, Zhi Wang,
Balbir Singh, Philipp Stanner, Elle Rhumsaa, alexeyi,
Eliot Courtney, joel, linux-doc, amd-gfx, intel-gfx, intel-xe,
linux-fbdev, Joel Fernandes
This patch adds safe Rust abstractions over the Linux kernel's GPU buddy
allocator for physical memory management. The prerequisite infrastructure
patches (DRM buddy code movement and the uninitialized buddy fix) have been
absorbed into upstream -next, so this is now a set of standalone patches.
The series along with all dependencies, including clist and nova-core mm
patches, are available at:
git://git.kernel.org/pub/scm/linux/kernel/git/jfern/linux.git (tag: buddy-bindings-v14-20260319)
Change log:
Changes from v13 to v14:
- Changed clist_create! call site to use explicit unsafe{} block.
- Various changes to change to Range type for ranges (Alex).
- Renamed GpuBuddyParams::physical_memory_size to size (Alex).
- Changed GpuBuddyAllocFlags inner type from u32 to usize (Alex).
- Renamed free_memory() to avail() (Alex).
- Various nits (Alex).
Changes from v12 to v13:
- Split MAINTAINERS reviewer update into a separate patch (Danilo).
- Adjustments to use the Alignment type chunk size parameters (Alex).
- Fixed doctest assertion due to blocks landing on top of range.
- Changed chunk_size local vars to Alignment.
- Changed block size to u64 from usize.
- Renamed rust/kernel/gpu/mod.rs to rust/kernel/gpu.rs.
- Several other adjustments (Alex).
Changes from v11 to v12:
- Rebased on linux-next his is now a standalone single patch as dependencies
are absorbed (but not clist is a prequisite)
- Redesigned allocation API (Alexandre Courbot) for better Rust ergonomics.
- Split single long example into 4 self-contained examples (Alexandre Courbot).
- Several safety and invariant comment changes (Danilo).
- MAINTAINERS changes (Arun, Mathew, Danilo, Dave).
- Fixed `#[cfg(CONFIG_GPU_BUDDY)]` to `#[cfg(CONFIG_GPU_BUDDY = "y")]` (Danilo Krummrich).
- Updated `ffi::clist::CListHead` to `interop::list::CListHead`.
Changes from v10 to v11:
- Dropped "rust: ffi: Convert pub use to pub mod and create ffi module" patch;
the ffi module restructuring will go through a different path.
- Dropped "rust: clist: Add support to interface with C linked lists" patch;
the clist module will be submitted separately.
- Dropped "nova-core: Kconfig: Sort select statements alphabetically" cosmetic
patch.
- Patches 1-3 (DRM buddy movement and fix) are included as reference only;
they are already being pulled into upstream via drm-misc-next.
- Removed clist patches as those can go in independently (Alice).
- Moved the Kconfig GPU_BUDDY selection patch to nova-core mm series to enable
it when it is actually used.
- Various nits to comments, etc.
Changes from v9 to v10:
- Absorbed the DRM buddy code movement patches into this series as patches 1-2.
Dave Airlie reworked these into two parts for better git history.
- Added "gpu: Fix uninitialized buddy for built-in drivers" fix by Koen Koning,
using subsys_initcall instead of module_init to fix NULL pointer dereference
when built-in drivers use the buddy allocator before initialization.
- Added "rust: ffi: Convert pub use to pub mod and create ffi module" to prepare
the ffi module for hosting clist as a sub-module.
- Moved clist from rust/kernel/clist.rs to rust/kernel/ffi/.
- Added "nova-core: Kconfig: Sort select statements alphabetically" (Danilo).
Changes from v8 to v9:
- Updated nova-core Kconfig patch: addressed sorting of Kconfig options.
- Added Daniel Almeida's Reviewed-by tag to clist patch.
- Minor refinements to GPU buddy bindings.
Changes from v7 to v8:
- Added nova-core Kconfig patch to select GPU_BUDDY for VRAM allocation.
- Various changes suggested by Danilo Krummrich, Gary Guo, and Daniel Almeida.
- Added Acked-by: Gary Guo for clist patch.
Changes from v6 to v7:
- Major restructuring: split the large 26-patch v6 RFC series. v7 only contains
the Rust infrastructure patches (clist + GPU buddy bindings), extracted from
the full nova-core MM series. The nova-core MM patches follow separately.
- Rebased on linux-next.
Changes from v5 to v6:
- Rebased on drm-rust-kernel/drm-rust-next.
- Expanded from 6 to 26 patches with full nova-core MM infrastructure including
page table walker, VMM, BAR1 user interface, TLB flush, and GpuMm manager.
Changes from v4 to v5:
- Added PRAMIN aperture support with documentation and self-tests.
- Improved buddy allocator bindings (fewer lines of code).
- Based on drm-rust-next instead of linux-next.
Changes from v3 to v4:
- Combined the clist and DRM buddy series into a single coherent series.
- Added DRM buddy allocator movement from drivers/gpu/drm/ up to drivers/gpu/,
renaming API from drm_buddy to gpu_buddy.
- Added Rust bindings for the GPU buddy allocator.
Changes from v2 to v3:
- Squashed 3 clist patches into one due to inter-dependencies.
- Changed Clist to Clist<'a, T> using const generic offset (Alex Courbot).
- Simplified C helpers to only list_add_tail (Alex Courbot, John Hubbard).
- Added init_list_head() Rust function (Alex Courbot).
- Added FusedIterator, PartialEq/Eq impls.
- Added MAINTAINERS entry (Miguel Ojeda).
Changes from v1 (RFC) to v2:
- Dropped DRM buddy allocator patches; series focuses solely on clist module.
- Dropped sample modules, replaced with doctests.
- Added proper lifetime management similar to scatterlist.
- Split clist into 3 separate patches.
Link to v13: https://lore.kernel.org/all/20260317220323.1909618-1-joelagnelf@nvidia.com/
Joel Fernandes (2):
rust: gpu: Add GPU buddy allocator bindings
MAINTAINERS: gpu: buddy: Update reviewer
MAINTAINERS | 8 +-
rust/bindings/bindings_helper.h | 11 +
rust/helpers/gpu.c | 23 ++
rust/helpers/helpers.c | 1 +
rust/kernel/gpu.rs | 6 +
rust/kernel/gpu/buddy.rs | 613 ++++++++++++++++++++++++++++++++
rust/kernel/lib.rs | 2 +
7 files changed, 663 insertions(+), 1 deletion(-)
create mode 100644 rust/helpers/gpu.c
create mode 100644 rust/kernel/gpu.rs
create mode 100644 rust/kernel/gpu/buddy.rs
--
2.34.1
^ permalink raw reply
* Re: [PATCH v9 7/7] PCI/TPH: Fix get cpu steer-tag fail on ARM64 platform
From: fengchengwen @ 2026-03-20 3:26 UTC (permalink / raw)
To: Bjorn Helgaas
Cc: Bjorn Helgaas, Catalin Marinas, Will Deacon, Rafael J . Wysocki,
Jonathan Corbet, Shuah Khan, Huacai Chen, WANG Xuerui,
Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
H . Peter Anvin, Juergen Gross, Boris Ostrovsky, Len Brown,
Sunil V L, Mark Rutland, Jonathan Cameron, Kees Cook, Yanteng Si,
Sean Christopherson, Kai Huang, Tom Lendacky, Thomas Huth,
Thorsten Blum, Kevin Loughlin, Zheyun Shen, Peter Zijlstra,
Pawan Gupta, Xin Li, Ahmed S . Darwish, Sohil Mehta,
Ilkka Koskinen, Robin Murphy, James Clark, Besar Wicaksono, Ma Ke,
Wei Huang, Andy Gospodarek, Somnath Kotur, punit.agrawal,
guohanjun, suzuki.poulose, ryan.roberts, chenl311, masahiroy,
wangyuquan1236, anshuman.khandual, heinrich.schuchardt,
Eric.VanTassell, wangzhou1, wanghuiqiang, liuyonglong, linux-pci,
linux-doc, linux-kernel, linux-arm-kernel, loongarch, linux-riscv,
xen-devel, linux-acpi, linux-perf-users, stable
In-Reply-To: <20260319183219.GA519221@bhelgaas>
On 3/20/2026 2:32 AM, Bjorn Helgaas wrote:
> Let's make the subject a little more specific, e.g.,
>
> PCI/TPH: Pass ACPI Processor UID to Cache Locality _DSM
done in v10
>
> On Thu, Mar 19, 2026 at 02:57:35PM +0800, Chengwen Feng wrote:
>> pcie_tph_get_cpu_st() is broken on ARM64:
>> 1. pcie_tph_get_cpu_st() passes cpu_uid to the PCI ACPI DSM method.
>> cpu_uid should be the ACPI Processor UID [1].
>> 2. In BNXT, pcie_tph_get_cpu_st() is passed a cpu_uid obtained via
>> cpumask_first(irq->cpu_mask) - the logical CPU ID of a CPU core,
>> generated and managed by kernel (e.g., [0,255] for a system with 256
>> logical CPU cores).
>> 3. On ARM64 platforms, ACPI assigns Processor UID to cores listed in the
>> MADT table, and this UID may not match the kernel's logical CPU ID.
>> When this occurs, the mismatch results in the wrong CPU steer-tag.
>> 4. On AMD x86 the logical CPU ID is identical to the ACPI Processor UID
>> so the mismatch is not seen.
>>
>> Resolution:
>> 1. Use acpi_get_cpu_uid() in pcie_tph_get_cpu_st() to translate from
>> logical CPU ID to ACPI Processor UID needed for the DSM call.
>> 2. Rename pcie_tpu_get_cpu_st() parameter from cpu_uid to cpu to
>> reflect that it is a logical CPU_ID.
>
> And simplify this, e.g.,
>
> pcie_tph_get_cpu_st() uses the Query Cache Locality Features _DSM
> [1] to retrieve the TPH Steering Tag for memory associated with the
> CPU identified by its "cpu_uid" parameter, a Linux logical CPU ID.
>
> The _DSM requires a ACPI Processor UID, which pcie_tph_get_cpu_st()
> previously assumed was the same as the Linux logical CPU ID. This
> is true on x86 but not on arm64, so pcie_tph_get_cpu_st() failed on
> arm64.
>
> Convert the Linux logical CPU ID to the ACPI Processor UID with
> acpi_get_cpu_uid() before passing it to the _DSM.
>
> If there's a specific error message from BNXT or similar that is a
> symptom of this problem, it'd be nice to include that. Or if the
> problem was just poor performance because the _DSM returned the wrong
> Steering Tag, you could say something like:
>
> ... so pcie_tph_get_cpu_st() returned the wrong Steering Tag,
> resulting in poor network performance.
It is indeed simplified, done in v10
>
>> [1] According to ECN_TPH-ST_Revision_20200924
>> (https://members.pcisig.com/wg/PCI-SIG/document/15470), the input
>> is defined as: "If the target is a processor, then this field
>> represents the ACPI Processor UID of the processor as specified in
>> the MADT. If the target is a processor container, then this field
>> represents the ACPI Processor UID of the processor container as
>> specified in the PPTT."
>>
>> Fixes: d2e8a34876ce ("PCI/TPH: Add Steering Tag support")
>> Cc: stable@vger.kernel.org
>> Signed-off-by: Chengwen Feng <fengchengwen@huawei.com>
>> Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
>
> The patch looks good to me. Thanks for all your work on this!
>
> Reviewed-by: Bjorn Helgaas <bhelgaas@google.com>
Thanks Bjorn for your review and kind words! I really appreciate it.
>
>> ---
>> Documentation/PCI/tph.rst | 4 ++--
>> drivers/pci/tph.c | 16 +++++++++++-----
>> include/linux/pci-tph.h | 4 ++--
>> 3 files changed, 15 insertions(+), 9 deletions(-)
>>
>> diff --git a/Documentation/PCI/tph.rst b/Documentation/PCI/tph.rst
>> index e8993be64fd6..b6cf22b9bd90 100644
>> --- a/Documentation/PCI/tph.rst
>> +++ b/Documentation/PCI/tph.rst
>> @@ -79,10 +79,10 @@ To retrieve a Steering Tag for a target memory associated with a specific
>> CPU, use the following function::
>>
>> int pcie_tph_get_cpu_st(struct pci_dev *pdev, enum tph_mem_type type,
>> - unsigned int cpu_uid, u16 *tag);
>> + unsigned int cpu, u16 *tag);
>>
>> The `type` argument is used to specify the memory type, either volatile
>> -or persistent, of the target memory. The `cpu_uid` argument specifies the
>> +or persistent, of the target memory. The `cpu` argument specifies the
>> CPU where the memory is associated to.
>>
>> After the ST value is retrieved, the device driver can use the following
>> diff --git a/drivers/pci/tph.c b/drivers/pci/tph.c
>> index ca4f97be7538..b67c9ad14bda 100644
>> --- a/drivers/pci/tph.c
>> +++ b/drivers/pci/tph.c
>> @@ -236,21 +236,27 @@ static int write_tag_to_st_table(struct pci_dev *pdev, int index, u16 tag)
>> * with a specific CPU
>> * @pdev: PCI device
>> * @mem_type: target memory type (volatile or persistent RAM)
>> - * @cpu_uid: associated CPU id
>> + * @cpu: associated CPU id
>> * @tag: Steering Tag to be returned
>> *
>> * Return the Steering Tag for a target memory that is associated with a
>> - * specific CPU as indicated by cpu_uid.
>> + * specific CPU as indicated by cpu.
>> *
>> * Return: 0 if success, otherwise negative value (-errno)
>> */
>> int pcie_tph_get_cpu_st(struct pci_dev *pdev, enum tph_mem_type mem_type,
>> - unsigned int cpu_uid, u16 *tag)
>> + unsigned int cpu, u16 *tag)
>> {
>> #ifdef CONFIG_ACPI
>> struct pci_dev *rp;
>> acpi_handle rp_acpi_handle;
>> union st_info info;
>> + u32 cpu_uid;
>> + int ret;
>> +
>> + ret = acpi_get_cpu_uid(cpu, &cpu_uid);
>> + if (ret != 0)
>> + return ret;
>>
>> rp = pcie_find_root_port(pdev);
>> if (!rp || !rp->bus || !rp->bus->bridge)
>> @@ -265,9 +271,9 @@ int pcie_tph_get_cpu_st(struct pci_dev *pdev, enum tph_mem_type mem_type,
>>
>> *tag = tph_extract_tag(mem_type, pdev->tph_req_type, &info);
>>
>> - pci_dbg(pdev, "get steering tag: mem_type=%s, cpu_uid=%d, tag=%#04x\n",
>> + pci_dbg(pdev, "get steering tag: mem_type=%s, cpu=%d, tag=%#04x\n",
>> (mem_type == TPH_MEM_TYPE_VM) ? "volatile" : "persistent",
>> - cpu_uid, *tag);
>> + cpu, *tag);
>>
>> return 0;
>> #else
>> diff --git a/include/linux/pci-tph.h b/include/linux/pci-tph.h
>> index ba28140ce670..be68cd17f2f8 100644
>> --- a/include/linux/pci-tph.h
>> +++ b/include/linux/pci-tph.h
>> @@ -25,7 +25,7 @@ int pcie_tph_set_st_entry(struct pci_dev *pdev,
>> unsigned int index, u16 tag);
>> int pcie_tph_get_cpu_st(struct pci_dev *dev,
>> enum tph_mem_type mem_type,
>> - unsigned int cpu_uid, u16 *tag);
>> + unsigned int cpu, u16 *tag);
>> void pcie_disable_tph(struct pci_dev *pdev);
>> int pcie_enable_tph(struct pci_dev *pdev, int mode);
>> u16 pcie_tph_get_st_table_size(struct pci_dev *pdev);
>> @@ -36,7 +36,7 @@ static inline int pcie_tph_set_st_entry(struct pci_dev *pdev,
>> { return -EINVAL; }
>> static inline int pcie_tph_get_cpu_st(struct pci_dev *dev,
>> enum tph_mem_type mem_type,
>> - unsigned int cpu_uid, u16 *tag)
>> + unsigned int cpu, u16 *tag)
>> { return -EINVAL; }
>> static inline void pcie_disable_tph(struct pci_dev *pdev) { }
>> static inline int pcie_enable_tph(struct pci_dev *pdev, int mode)
>> --
>> 2.17.1
>>
>
^ permalink raw reply
* Re: [PATCH v9 1/7] arm64/acpi: Add acpi_get_cpu_uid() and switch arm_cspmu to use it
From: fengchengwen @ 2026-03-20 3:20 UTC (permalink / raw)
To: Punit Agrawal
Cc: Bjorn Helgaas, Catalin Marinas, Will Deacon, Rafael J . Wysocki,
Jonathan Corbet, Shuah Khan, Huacai Chen, WANG Xuerui,
Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
H . Peter Anvin, Juergen Gross, Boris Ostrovsky, Len Brown,
Sunil V L, Mark Rutland, Jonathan Cameron, Kees Cook, Yanteng Si,
Sean Christopherson, Kai Huang, Tom Lendacky, Thomas Huth,
Thorsten Blum, Kevin Loughlin, Zheyun Shen, Peter Zijlstra,
Pawan Gupta, Xin Li, Ahmed S . Darwish, Sohil Mehta,
Ilkka Koskinen, Robin Murphy, James Clark, Besar Wicaksono, Ma Ke,
Wei Huang, Andy Gospodarek, Somnath Kotur, guohanjun,
suzuki.poulose, ryan.roberts, chenl311, masahiroy, wangyuquan1236,
anshuman.khandual, heinrich.schuchardt, Eric.VanTassell,
wangzhou1, wanghuiqiang, liuyonglong, linux-pci, linux-doc,
linux-kernel, linux-arm-kernel, loongarch, linux-riscv, xen-devel,
linux-acpi, linux-perf-users, stable
In-Reply-To: <87341vq0u1.fsf@stealth>
On 3/19/2026 11:46 PM, Punit Agrawal wrote:
> Chengwen Feng <fengchengwen@huawei.com> writes:
>
>> Add arch-specific acpi_get_cpu_uid() for arm64, and update dependent
>> code:
>> - Declare acpi_get_cpu_uid() in arch/arm64/include/asm/acpi.h
>> - Implement acpi_get_cpu_uid() with input parameter validation
>> - Replace get_acpi_id_for_cpu() with acpi_get_cpu_uid() in
>> drivers/perf/arm_cspmu/arm_cspmu.c
>> - Reimplement get_cpu_for_acpi_id() based on acpi_get_cpu_uid() (to
>> align with new interface) and move its implementation next to
>> acpi_get_cpu_uid()
>
> There is no benefit in describing the code changes like this in the
> commit log. It makes it hard to follow the intent of the patch.
>
>> This is the first step towards unifying ACPI CPU UID retrieval interface
>> across architectures, while adding input validation for robustness.
>
> I would simplify the commit log to something along the lines of -
>
> As a step towards unifying the interface for retrieving ACPI CPU uid
> across architectures, introduce a new function
> acpi_get_cpu_uid(). While at it, also add input validation to make
> the code more robust.
Thank you for your advice.
I've reviewed all the commit logs and made some optimizations, and done in v10
>
> Just my 2c.
>
> The code changes looks fine.
>
>> Cc: stable@vger.kernel.org
>> Signed-off-by: Chengwen Feng <fengchengwen@huawei.com>
>> Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
>> ---
>> arch/arm64/include/asm/acpi.h | 14 ++------------
>> arch/arm64/kernel/acpi.c | 30 ++++++++++++++++++++++++++++++
>> drivers/perf/arm_cspmu/arm_cspmu.c | 6 ++++--
>> 3 files changed, 36 insertions(+), 14 deletions(-)
>>
>> diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h
>> index c07a58b96329..2219a3301e72 100644
>> --- a/arch/arm64/include/asm/acpi.h
>> +++ b/arch/arm64/include/asm/acpi.h
>> @@ -118,18 +118,8 @@ static inline u32 get_acpi_id_for_cpu(unsigned int cpu)
>> {
>> return acpi_cpu_get_madt_gicc(cpu)->uid;
>> }
>> -
>> -static inline int get_cpu_for_acpi_id(u32 uid)
>> -{
>> - int cpu;
>> -
>> - for (cpu = 0; cpu < nr_cpu_ids; cpu++)
>> - if (acpi_cpu_get_madt_gicc(cpu) &&
>> - uid == get_acpi_id_for_cpu(cpu))
>> - return cpu;
>> -
>> - return -EINVAL;
>> -}
>> +int acpi_get_cpu_uid(unsigned int cpu, u32 *uid);
>> +int get_cpu_for_acpi_id(u32 uid);
>>
>> static inline void arch_fix_phys_package_id(int num, u32 slot) { }
>> void __init acpi_init_cpus(void);
>> diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c
>> index af90128cfed5..24b9d934be54 100644
>> --- a/arch/arm64/kernel/acpi.c
>> +++ b/arch/arm64/kernel/acpi.c
>> @@ -458,3 +458,33 @@ int acpi_unmap_cpu(int cpu)
>> }
>> EXPORT_SYMBOL(acpi_unmap_cpu);
>> #endif /* CONFIG_ACPI_HOTPLUG_CPU */
>> +
>> +int acpi_get_cpu_uid(unsigned int cpu, u32 *uid)
>> +{
>> + struct acpi_madt_generic_interrupt *gicc;
>> +
>> + if (cpu >= nr_cpu_ids)
>> + return -EINVAL;
>> +
>> + gicc = acpi_cpu_get_madt_gicc(cpu);
>> + if (!gicc)
>> + return -ENODEV;
>> +
>> + *uid = gicc->uid;
>> + return 0;
>> +}
>> +EXPORT_SYMBOL_GPL(acpi_get_cpu_uid);
>> +
>> +int get_cpu_for_acpi_id(u32 uid)
>> +{
>> + u32 cpu_uid;
>> + int ret;
>> +
>> + for (int cpu = 0; cpu < nr_cpu_ids; cpu++) {
>> + ret = acpi_get_cpu_uid(cpu, &cpu_uid);
>> + if (ret == 0 && uid == cpu_uid)
>> + return cpu;
>> + }
>> +
>> + return -EINVAL;
>> +}
>> diff --git a/drivers/perf/arm_cspmu/arm_cspmu.c b/drivers/perf/arm_cspmu/arm_cspmu.c
>> index 34430b68f602..ed72c3d1f796 100644
>> --- a/drivers/perf/arm_cspmu/arm_cspmu.c
>> +++ b/drivers/perf/arm_cspmu/arm_cspmu.c
>> @@ -1107,15 +1107,17 @@ static int arm_cspmu_acpi_get_cpus(struct arm_cspmu *cspmu)
>> {
>> struct acpi_apmt_node *apmt_node;
>> int affinity_flag;
>> + u32 cpu_uid;
>> int cpu;
>> + int ret;
>>
>> apmt_node = arm_cspmu_apmt_node(cspmu->dev);
>> affinity_flag = apmt_node->flags & ACPI_APMT_FLAGS_AFFINITY;
>>
>> if (affinity_flag == ACPI_APMT_FLAGS_AFFINITY_PROC) {
>> for_each_possible_cpu(cpu) {
>> - if (apmt_node->proc_affinity ==
>> - get_acpi_id_for_cpu(cpu)) {
>> + ret = acpi_get_cpu_uid(cpu, &cpu_uid);
>> + if (ret == 0 && apmt_node->proc_affinity == cpu_uid) {
>> cpumask_set_cpu(cpu, &cspmu->associated_cpus);
>> break;
>> }
>
> I think cspmu changes go via a separate pull request. You might have to
> split this change into a separate commit.
done in v10
Thanks
^ permalink raw reply
* [PATCH v10 8/8] PCI/TPH: Pass ACPI Processor UID to Cache Locality _DSM
From: Chengwen Feng @ 2026-03-20 3:17 UTC (permalink / raw)
To: Bjorn Helgaas, Catalin Marinas, Will Deacon, Rafael J . Wysocki
Cc: Jonathan Corbet, Palmer Dabbelt, Borislav Petkov, H . Peter Anvin,
Juergen Gross, Boris Ostrovsky, Len Brown, Sunil V L,
Mark Rutland, Jonathan Cameron, Kees Cook, Yanteng Si,
Sean Christopherson, Kai Huang, Tom Lendacky, Thomas Huth,
Thorsten Blum, Kevin Loughlin, Zheyun Shen, Peter Zijlstra,
Pawan Gupta, Xin Li, Ahmed S . Darwish, Sohil Mehta,
Ilkka Koskinen, Robin Murphy, James Clark, Besar Wicaksono, Ma Ke,
Wei Huang, Andy Gospodarek, Somnath Kotur, punit.agrawal,
guohanjun, suzuki.poulose, ryan.roberts, chenl311, masahiroy,
wangyuquan1236, anshuman.khandual, heinrich.schuchardt,
Eric.VanTassell, wangzhou1, wanghuiqiang, liuyonglong,
fengchengwen, linux-pci, linux-doc, linux-kernel,
linux-arm-kernel, loongarch, linux-riscv, xen-devel, linux-acpi,
linux-perf-users, stable
In-Reply-To: <20260320031737.35048-1-fengchengwen@huawei.com>
pcie_tph_get_cpu_st() uses the Query Cache Locality Features _DSM [1]
to retrieve the TPH Steering Tag for memory associated with the CPU
identified by its "cpu_uid" parameter, a Linux logical CPU ID.
The _DSM requires an ACPI Processor UID, which pcie_tph_get_cpu_st()
previously assumed was the same as the Linux logical CPU ID. This is
true on x86 but not on arm64, so pcie_tph_get_cpu_st() returned the
wrong Steering Tag, resulting in incorrect TPH functionality on arm64.
Convert the Linux logical CPU ID to the ACPI Processor UID with
acpi_get_cpu_uid() before passing it to the _DSM. Additionally, rename
the pcie_tph_get_cpu_st() parameter from "cpu_uid" to "cpu" to reflect
that it represents a logical CPU ID (not an ACPI Processor UID).
[1] According to ECN_TPH-ST_Revision_20200924
(https://members.pcisig.com/wg/PCI-SIG/document/15470), the input
is defined as: "If the target is a processor, then this field
represents the ACPI Processor UID of the processor as specified in
the MADT. If the target is a processor container, then this field
represents the ACPI Processor UID of the processor container as
specified in the PPTT."
Fixes: d2e8a34876ce ("PCI/TPH: Add Steering Tag support")
Cc: stable@vger.kernel.org
Signed-off-by: Chengwen Feng <fengchengwen@huawei.com>
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
Reviewed-by: Bjorn Helgaas <bhelgaas@google.com>
---
Documentation/PCI/tph.rst | 4 ++--
drivers/pci/tph.c | 16 +++++++++++-----
include/linux/pci-tph.h | 4 ++--
3 files changed, 15 insertions(+), 9 deletions(-)
diff --git a/Documentation/PCI/tph.rst b/Documentation/PCI/tph.rst
index e8993be64fd6..b6cf22b9bd90 100644
--- a/Documentation/PCI/tph.rst
+++ b/Documentation/PCI/tph.rst
@@ -79,10 +79,10 @@ To retrieve a Steering Tag for a target memory associated with a specific
CPU, use the following function::
int pcie_tph_get_cpu_st(struct pci_dev *pdev, enum tph_mem_type type,
- unsigned int cpu_uid, u16 *tag);
+ unsigned int cpu, u16 *tag);
The `type` argument is used to specify the memory type, either volatile
-or persistent, of the target memory. The `cpu_uid` argument specifies the
+or persistent, of the target memory. The `cpu` argument specifies the
CPU where the memory is associated to.
After the ST value is retrieved, the device driver can use the following
diff --git a/drivers/pci/tph.c b/drivers/pci/tph.c
index ca4f97be7538..b67c9ad14bda 100644
--- a/drivers/pci/tph.c
+++ b/drivers/pci/tph.c
@@ -236,21 +236,27 @@ static int write_tag_to_st_table(struct pci_dev *pdev, int index, u16 tag)
* with a specific CPU
* @pdev: PCI device
* @mem_type: target memory type (volatile or persistent RAM)
- * @cpu_uid: associated CPU id
+ * @cpu: associated CPU id
* @tag: Steering Tag to be returned
*
* Return the Steering Tag for a target memory that is associated with a
- * specific CPU as indicated by cpu_uid.
+ * specific CPU as indicated by cpu.
*
* Return: 0 if success, otherwise negative value (-errno)
*/
int pcie_tph_get_cpu_st(struct pci_dev *pdev, enum tph_mem_type mem_type,
- unsigned int cpu_uid, u16 *tag)
+ unsigned int cpu, u16 *tag)
{
#ifdef CONFIG_ACPI
struct pci_dev *rp;
acpi_handle rp_acpi_handle;
union st_info info;
+ u32 cpu_uid;
+ int ret;
+
+ ret = acpi_get_cpu_uid(cpu, &cpu_uid);
+ if (ret != 0)
+ return ret;
rp = pcie_find_root_port(pdev);
if (!rp || !rp->bus || !rp->bus->bridge)
@@ -265,9 +271,9 @@ int pcie_tph_get_cpu_st(struct pci_dev *pdev, enum tph_mem_type mem_type,
*tag = tph_extract_tag(mem_type, pdev->tph_req_type, &info);
- pci_dbg(pdev, "get steering tag: mem_type=%s, cpu_uid=%d, tag=%#04x\n",
+ pci_dbg(pdev, "get steering tag: mem_type=%s, cpu=%d, tag=%#04x\n",
(mem_type == TPH_MEM_TYPE_VM) ? "volatile" : "persistent",
- cpu_uid, *tag);
+ cpu, *tag);
return 0;
#else
diff --git a/include/linux/pci-tph.h b/include/linux/pci-tph.h
index ba28140ce670..be68cd17f2f8 100644
--- a/include/linux/pci-tph.h
+++ b/include/linux/pci-tph.h
@@ -25,7 +25,7 @@ int pcie_tph_set_st_entry(struct pci_dev *pdev,
unsigned int index, u16 tag);
int pcie_tph_get_cpu_st(struct pci_dev *dev,
enum tph_mem_type mem_type,
- unsigned int cpu_uid, u16 *tag);
+ unsigned int cpu, u16 *tag);
void pcie_disable_tph(struct pci_dev *pdev);
int pcie_enable_tph(struct pci_dev *pdev, int mode);
u16 pcie_tph_get_st_table_size(struct pci_dev *pdev);
@@ -36,7 +36,7 @@ static inline int pcie_tph_set_st_entry(struct pci_dev *pdev,
{ return -EINVAL; }
static inline int pcie_tph_get_cpu_st(struct pci_dev *dev,
enum tph_mem_type mem_type,
- unsigned int cpu_uid, u16 *tag)
+ unsigned int cpu, u16 *tag)
{ return -EINVAL; }
static inline void pcie_disable_tph(struct pci_dev *pdev) { }
static inline int pcie_enable_tph(struct pci_dev *pdev, int mode)
--
2.17.1
^ permalink raw reply related
* [PATCH v10 7/8] ACPI: PPTT: Use acpi_get_cpu_uid() and remove get_acpi_id_for_cpu()
From: Chengwen Feng @ 2026-03-20 3:17 UTC (permalink / raw)
To: Bjorn Helgaas, Catalin Marinas, Will Deacon, Rafael J . Wysocki
Cc: Jonathan Corbet, Palmer Dabbelt, Borislav Petkov, H . Peter Anvin,
Juergen Gross, Boris Ostrovsky, Len Brown, Sunil V L,
Mark Rutland, Jonathan Cameron, Kees Cook, Yanteng Si,
Sean Christopherson, Kai Huang, Tom Lendacky, Thomas Huth,
Thorsten Blum, Kevin Loughlin, Zheyun Shen, Peter Zijlstra,
Pawan Gupta, Xin Li, Ahmed S . Darwish, Sohil Mehta,
Ilkka Koskinen, Robin Murphy, James Clark, Besar Wicaksono, Ma Ke,
Wei Huang, Andy Gospodarek, Somnath Kotur, punit.agrawal,
guohanjun, suzuki.poulose, ryan.roberts, chenl311, masahiroy,
wangyuquan1236, anshuman.khandual, heinrich.schuchardt,
Eric.VanTassell, wangzhou1, wanghuiqiang, liuyonglong,
fengchengwen, linux-pci, linux-doc, linux-kernel,
linux-arm-kernel, loongarch, linux-riscv, xen-devel, linux-acpi,
linux-perf-users, stable
In-Reply-To: <20260320031737.35048-1-fengchengwen@huawei.com>
Update acpi/pptt.c to use acpi_get_cpu_uid() and remove unused
get_acpi_id_for_cpu() from arm64/loongarch/riscv, completing PPTT's
migration to the unified ACPI CPU UID interface
Cc: stable@vger.kernel.org
Signed-off-by: Chengwen Feng <fengchengwen@huawei.com>
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
---
arch/arm64/include/asm/acpi.h | 4 ---
arch/loongarch/include/asm/acpi.h | 5 ----
arch/riscv/include/asm/acpi.h | 4 ---
drivers/acpi/pptt.c | 50 +++++++++++++++++++++++--------
4 files changed, 37 insertions(+), 26 deletions(-)
diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h
index bdb0ecf95b5c..8a54ca6ba602 100644
--- a/arch/arm64/include/asm/acpi.h
+++ b/arch/arm64/include/asm/acpi.h
@@ -114,10 +114,6 @@ static inline bool acpi_has_cpu_in_madt(void)
}
struct acpi_madt_generic_interrupt *acpi_cpu_get_madt_gicc(int cpu);
-static inline u32 get_acpi_id_for_cpu(unsigned int cpu)
-{
- return acpi_cpu_get_madt_gicc(cpu)->uid;
-}
int get_cpu_for_acpi_id(u32 uid);
static inline void arch_fix_phys_package_id(int num, u32 slot) { }
diff --git a/arch/loongarch/include/asm/acpi.h b/arch/loongarch/include/asm/acpi.h
index 7376840fa9f7..eda9d4d0a493 100644
--- a/arch/loongarch/include/asm/acpi.h
+++ b/arch/loongarch/include/asm/acpi.h
@@ -40,11 +40,6 @@ extern struct acpi_madt_core_pic acpi_core_pic[MAX_CORE_PIC];
extern int __init parse_acpi_topology(void);
-static inline u32 get_acpi_id_for_cpu(unsigned int cpu)
-{
- return acpi_core_pic[cpu_logical_map(cpu)].processor_id;
-}
-
#endif /* !CONFIG_ACPI */
#define ACPI_TABLE_UPGRADE_MAX_PHYS ARCH_LOW_ADDRESS_LIMIT
diff --git a/arch/riscv/include/asm/acpi.h b/arch/riscv/include/asm/acpi.h
index 6e13695120bc..26ab37c171bc 100644
--- a/arch/riscv/include/asm/acpi.h
+++ b/arch/riscv/include/asm/acpi.h
@@ -61,10 +61,6 @@ static inline void arch_fix_phys_package_id(int num, u32 slot) { }
void acpi_init_rintc_map(void);
struct acpi_madt_rintc *acpi_cpu_get_madt_rintc(int cpu);
-static inline u32 get_acpi_id_for_cpu(int cpu)
-{
- return acpi_cpu_get_madt_rintc(cpu)->uid;
-}
int acpi_get_riscv_isa(struct acpi_table_header *table,
unsigned int cpu, const char **isa);
diff --git a/drivers/acpi/pptt.c b/drivers/acpi/pptt.c
index de5f8c018333..7bd5bc1f225a 100644
--- a/drivers/acpi/pptt.c
+++ b/drivers/acpi/pptt.c
@@ -459,11 +459,14 @@ static void cache_setup_acpi_cpu(struct acpi_table_header *table,
{
struct acpi_pptt_cache *found_cache;
struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
- u32 acpi_cpu_id = get_acpi_id_for_cpu(cpu);
+ u32 acpi_cpu_id;
struct cacheinfo *this_leaf;
unsigned int index = 0;
struct acpi_pptt_processor *cpu_node = NULL;
+ if (acpi_get_cpu_uid(cpu, &acpi_cpu_id) != 0)
+ return;
+
while (index < get_cpu_cacheinfo(cpu)->num_leaves) {
this_leaf = this_cpu_ci->info_list + index;
found_cache = acpi_find_cache_node(table, acpi_cpu_id,
@@ -546,7 +549,10 @@ static int topology_get_acpi_cpu_tag(struct acpi_table_header *table,
unsigned int cpu, int level, int flag)
{
struct acpi_pptt_processor *cpu_node;
- u32 acpi_cpu_id = get_acpi_id_for_cpu(cpu);
+ u32 acpi_cpu_id;
+
+ if (acpi_get_cpu_uid(cpu, &acpi_cpu_id) != 0)
+ return -ENOENT;
cpu_node = acpi_find_processor_node(table, acpi_cpu_id);
if (cpu_node) {
@@ -614,18 +620,22 @@ static int find_acpi_cpu_topology_tag(unsigned int cpu, int level, int flag)
*
* Check the node representing a CPU for a given flag.
*
- * Return: -ENOENT if the PPTT doesn't exist, the CPU cannot be found or
- * the table revision isn't new enough.
+ * Return: -ENOENT if can't get CPU's ACPI Processor UID, the PPTT doesn't
+ * exist, the CPU cannot be found or the table revision isn't new
+ * enough.
* 1, any passed flag set
* 0, flag unset
*/
static int check_acpi_cpu_flag(unsigned int cpu, int rev, u32 flag)
{
struct acpi_table_header *table;
- u32 acpi_cpu_id = get_acpi_id_for_cpu(cpu);
+ u32 acpi_cpu_id;
struct acpi_pptt_processor *cpu_node = NULL;
int ret = -ENOENT;
+ if (acpi_get_cpu_uid(cpu, &acpi_cpu_id) != 0)
+ return -ENOENT;
+
table = acpi_get_pptt();
if (!table)
return -ENOENT;
@@ -651,7 +661,8 @@ static int check_acpi_cpu_flag(unsigned int cpu, int rev, u32 flag)
* in the PPTT. Errors caused by lack of a PPTT table, or otherwise, return 0
* indicating we didn't find any cache levels.
*
- * Return: -ENOENT if no PPTT table or no PPTT processor struct found.
+ * Return: -ENOENT if no PPTT table, can't get CPU's ACPI Process UID or no PPTT
+ * processor struct found.
* 0 on success.
*/
int acpi_get_cache_info(unsigned int cpu, unsigned int *levels,
@@ -671,7 +682,9 @@ int acpi_get_cache_info(unsigned int cpu, unsigned int *levels,
pr_debug("Cache Setup: find cache levels for CPU=%d\n", cpu);
- acpi_cpu_id = get_acpi_id_for_cpu(cpu);
+ if (acpi_get_cpu_uid(cpu, &acpi_cpu_id))
+ return -ENOENT;
+
cpu_node = acpi_find_processor_node(table, acpi_cpu_id);
if (!cpu_node)
return -ENOENT;
@@ -780,8 +793,9 @@ int find_acpi_cpu_topology_package(unsigned int cpu)
* It may not exist in single CPU systems. In simple multi-CPU systems,
* it may be equal to the package topology level.
*
- * Return: -ENOENT if the PPTT doesn't exist, the CPU cannot be found
- * or there is no toplogy level above the CPU..
+ * Return: -ENOENT if the PPTT doesn't exist, can't get CPU's ACPI
+ * Processor UID, the CPU cannot be found or there is no toplogy level
+ * above the CPU.
* Otherwise returns a value which represents the package for this CPU.
*/
@@ -797,7 +811,9 @@ int find_acpi_cpu_topology_cluster(unsigned int cpu)
if (!table)
return -ENOENT;
- acpi_cpu_id = get_acpi_id_for_cpu(cpu);
+ if (acpi_get_cpu_uid(cpu, &acpi_cpu_id) != 0)
+ return -ENOENT;
+
cpu_node = acpi_find_processor_node(table, acpi_cpu_id);
if (!cpu_node || !cpu_node->parent)
return -ENOENT;
@@ -872,7 +888,9 @@ static void acpi_pptt_get_child_cpus(struct acpi_table_header *table_hdr,
cpumask_clear(cpus);
for_each_possible_cpu(cpu) {
- acpi_id = get_acpi_id_for_cpu(cpu);
+ if (acpi_get_cpu_uid(cpu, &acpi_id) != 0)
+ continue;
+
cpu_node = acpi_find_processor_node(table_hdr, acpi_id);
while (cpu_node) {
@@ -966,10 +984,13 @@ int find_acpi_cache_level_from_id(u32 cache_id)
for_each_possible_cpu(cpu) {
bool empty;
int level = 1;
- u32 acpi_cpu_id = get_acpi_id_for_cpu(cpu);
+ u32 acpi_cpu_id;
struct acpi_pptt_cache *cache;
struct acpi_pptt_processor *cpu_node;
+ if (acpi_get_cpu_uid(cpu, &acpi_cpu_id) != 0)
+ continue;
+
cpu_node = acpi_find_processor_node(table, acpi_cpu_id);
if (!cpu_node)
continue;
@@ -1030,10 +1051,13 @@ int acpi_pptt_get_cpumask_from_cache_id(u32 cache_id, cpumask_t *cpus)
for_each_possible_cpu(cpu) {
bool empty;
int level = 1;
- u32 acpi_cpu_id = get_acpi_id_for_cpu(cpu);
+ u32 acpi_cpu_id;
struct acpi_pptt_cache *cache;
struct acpi_pptt_processor *cpu_node;
+ if (acpi_get_cpu_uid(cpu, &acpi_cpu_id) != 0)
+ continue;
+
cpu_node = acpi_find_processor_node(table, acpi_cpu_id);
if (!cpu_node)
continue;
--
2.17.1
^ permalink raw reply related
* [PATCH v10 6/8] perf: arm_cspmu: Switch to acpi_get_cpu_uid() from get_acpi_id_for_cpu()
From: Chengwen Feng @ 2026-03-20 3:17 UTC (permalink / raw)
To: Bjorn Helgaas, Catalin Marinas, Will Deacon, Rafael J . Wysocki
Cc: Jonathan Corbet, Palmer Dabbelt, Borislav Petkov, H . Peter Anvin,
Juergen Gross, Boris Ostrovsky, Len Brown, Sunil V L,
Mark Rutland, Jonathan Cameron, Kees Cook, Yanteng Si,
Sean Christopherson, Kai Huang, Tom Lendacky, Thomas Huth,
Thorsten Blum, Kevin Loughlin, Zheyun Shen, Peter Zijlstra,
Pawan Gupta, Xin Li, Ahmed S . Darwish, Sohil Mehta,
Ilkka Koskinen, Robin Murphy, James Clark, Besar Wicaksono, Ma Ke,
Wei Huang, Andy Gospodarek, Somnath Kotur, punit.agrawal,
guohanjun, suzuki.poulose, ryan.roberts, chenl311, masahiroy,
wangyuquan1236, anshuman.khandual, heinrich.schuchardt,
Eric.VanTassell, wangzhou1, wanghuiqiang, liuyonglong,
fengchengwen, linux-pci, linux-doc, linux-kernel,
linux-arm-kernel, loongarch, linux-riscv, xen-devel, linux-acpi,
linux-perf-users, stable
In-Reply-To: <20260320031737.35048-1-fengchengwen@huawei.com>
Update arm_cspmu to use acpi_get_cpu_uid() instead of
get_acpi_id_for_cpu(), aligning with unified ACPI CPU UID interface.
No functional changes are introduced by this switch (valid inputs retain
original behavior).
Cc: stable@vger.kernel.org
Signed-off-by: Chengwen Feng <fengchengwen@huawei.com>
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
---
drivers/perf/arm_cspmu/arm_cspmu.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/perf/arm_cspmu/arm_cspmu.c b/drivers/perf/arm_cspmu/arm_cspmu.c
index 34430b68f602..ed72c3d1f796 100644
--- a/drivers/perf/arm_cspmu/arm_cspmu.c
+++ b/drivers/perf/arm_cspmu/arm_cspmu.c
@@ -1107,15 +1107,17 @@ static int arm_cspmu_acpi_get_cpus(struct arm_cspmu *cspmu)
{
struct acpi_apmt_node *apmt_node;
int affinity_flag;
+ u32 cpu_uid;
int cpu;
+ int ret;
apmt_node = arm_cspmu_apmt_node(cspmu->dev);
affinity_flag = apmt_node->flags & ACPI_APMT_FLAGS_AFFINITY;
if (affinity_flag == ACPI_APMT_FLAGS_AFFINITY_PROC) {
for_each_possible_cpu(cpu) {
- if (apmt_node->proc_affinity ==
- get_acpi_id_for_cpu(cpu)) {
+ ret = acpi_get_cpu_uid(cpu, &cpu_uid);
+ if (ret == 0 && apmt_node->proc_affinity == cpu_uid) {
cpumask_set_cpu(cpu, &cspmu->associated_cpus);
break;
}
--
2.17.1
^ permalink raw reply related
* [PATCH v10 4/8] x86/acpi: Add acpi_get_cpu_uid() for unified ACPI CPU UID retrieval
From: Chengwen Feng @ 2026-03-20 3:17 UTC (permalink / raw)
To: Bjorn Helgaas, Catalin Marinas, Will Deacon, Rafael J . Wysocki
Cc: Jonathan Corbet, Palmer Dabbelt, Borislav Petkov, H . Peter Anvin,
Juergen Gross, Boris Ostrovsky, Len Brown, Sunil V L,
Mark Rutland, Jonathan Cameron, Kees Cook, Yanteng Si,
Sean Christopherson, Kai Huang, Tom Lendacky, Thomas Huth,
Thorsten Blum, Kevin Loughlin, Zheyun Shen, Peter Zijlstra,
Pawan Gupta, Xin Li, Ahmed S . Darwish, Sohil Mehta,
Ilkka Koskinen, Robin Murphy, James Clark, Besar Wicaksono, Ma Ke,
Wei Huang, Andy Gospodarek, Somnath Kotur, punit.agrawal,
guohanjun, suzuki.poulose, ryan.roberts, chenl311, masahiroy,
wangyuquan1236, anshuman.khandual, heinrich.schuchardt,
Eric.VanTassell, wangzhou1, wanghuiqiang, liuyonglong,
fengchengwen, linux-pci, linux-doc, linux-kernel,
linux-arm-kernel, loongarch, linux-riscv, xen-devel, linux-acpi,
linux-perf-users, stable
In-Reply-To: <20260320031737.35048-1-fengchengwen@huawei.com>
As a step towards unifying the interface for retrieving ACPI CPU UID
across architectures, introduce a new function acpi_get_cpu_uid() for
x86. While at it, add input validation to make the code more robust.
Update Xen-related code to use acpi_get_cpu_uid() instead of the legacy
cpu_acpi_id() function, and remove the now-unused cpu_acpi_id() to clean
up redundant code.
Cc: stable@vger.kernel.org
Signed-off-by: Chengwen Feng <fengchengwen@huawei.com>
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
Reviewed-by: Juergen Gross <jgross@suse.com>
---
arch/x86/include/asm/acpi.h | 2 ++
arch/x86/include/asm/cpu.h | 1 -
arch/x86/include/asm/smp.h | 1 -
arch/x86/kernel/acpi/boot.c | 20 ++++++++++++++++++++
arch/x86/xen/enlighten_hvm.c | 5 +++--
5 files changed, 25 insertions(+), 4 deletions(-)
diff --git a/arch/x86/include/asm/acpi.h b/arch/x86/include/asm/acpi.h
index a03aa6f999d1..92b5c27c4fea 100644
--- a/arch/x86/include/asm/acpi.h
+++ b/arch/x86/include/asm/acpi.h
@@ -157,6 +157,8 @@ static inline bool acpi_has_cpu_in_madt(void)
return !!acpi_lapic;
}
+int acpi_get_cpu_uid(unsigned int cpu, u32 *uid);
+
#define ACPI_HAVE_ARCH_SET_ROOT_POINTER
static __always_inline void acpi_arch_set_root_pointer(u64 addr)
{
diff --git a/arch/x86/include/asm/cpu.h b/arch/x86/include/asm/cpu.h
index ad235dda1ded..57a0786dfd75 100644
--- a/arch/x86/include/asm/cpu.h
+++ b/arch/x86/include/asm/cpu.h
@@ -11,7 +11,6 @@
#ifndef CONFIG_SMP
#define cpu_physical_id(cpu) boot_cpu_physical_apicid
-#define cpu_acpi_id(cpu) 0
#endif /* CONFIG_SMP */
#ifdef CONFIG_HOTPLUG_CPU
diff --git a/arch/x86/include/asm/smp.h b/arch/x86/include/asm/smp.h
index 84951572ab81..05d1d479b4cf 100644
--- a/arch/x86/include/asm/smp.h
+++ b/arch/x86/include/asm/smp.h
@@ -130,7 +130,6 @@ __visible void smp_call_function_interrupt(struct pt_regs *regs);
__visible void smp_call_function_single_interrupt(struct pt_regs *r);
#define cpu_physical_id(cpu) per_cpu(x86_cpu_to_apicid, cpu)
-#define cpu_acpi_id(cpu) per_cpu(x86_cpu_to_acpiid, cpu)
/*
* This function is needed by all SMP systems. It must _always_ be valid
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index a3f2fb1fea1b..ceba24f65ae3 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -1848,3 +1848,23 @@ void __iomem * (*acpi_os_ioremap)(acpi_physical_address phys, acpi_size size) =
x86_acpi_os_ioremap;
EXPORT_SYMBOL_GPL(acpi_os_ioremap);
#endif
+
+int acpi_get_cpu_uid(unsigned int cpu, u32 *uid)
+{
+ u32 acpi_id;
+
+ if (cpu >= nr_cpu_ids)
+ return -EINVAL;
+
+#ifdef CONFIG_SMP
+ acpi_id = per_cpu(x86_cpu_to_acpiid, cpu);
+ if (acpi_id == CPU_ACPIID_INVALID)
+ return -ENODEV;
+#else
+ acpi_id = 0;
+#endif
+
+ *uid = acpi_id;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(acpi_get_cpu_uid);
diff --git a/arch/x86/xen/enlighten_hvm.c b/arch/x86/xen/enlighten_hvm.c
index fe57ff85d004..2f9fa27e5a3c 100644
--- a/arch/x86/xen/enlighten_hvm.c
+++ b/arch/x86/xen/enlighten_hvm.c
@@ -151,6 +151,7 @@ static void xen_hvm_crash_shutdown(struct pt_regs *regs)
static int xen_cpu_up_prepare_hvm(unsigned int cpu)
{
+ u32 cpu_uid;
int rc = 0;
/*
@@ -161,8 +162,8 @@ static int xen_cpu_up_prepare_hvm(unsigned int cpu)
*/
xen_uninit_lock_cpu(cpu);
- if (cpu_acpi_id(cpu) != CPU_ACPIID_INVALID)
- per_cpu(xen_vcpu_id, cpu) = cpu_acpi_id(cpu);
+ if (acpi_get_cpu_uid(cpu, &cpu_uid) == 0)
+ per_cpu(xen_vcpu_id, cpu) = cpu_uid;
else
per_cpu(xen_vcpu_id, cpu) = cpu;
xen_vcpu_setup(cpu);
--
2.17.1
^ permalink raw reply related
* [PATCH v10 5/8] ACPI: Centralize acpi_get_cpu_uid() declaration in include/linux/acpi.h
From: Chengwen Feng @ 2026-03-20 3:17 UTC (permalink / raw)
To: Bjorn Helgaas, Catalin Marinas, Will Deacon, Rafael J . Wysocki
Cc: Jonathan Corbet, Palmer Dabbelt, Borislav Petkov, H . Peter Anvin,
Juergen Gross, Boris Ostrovsky, Len Brown, Sunil V L,
Mark Rutland, Jonathan Cameron, Kees Cook, Yanteng Si,
Sean Christopherson, Kai Huang, Tom Lendacky, Thomas Huth,
Thorsten Blum, Kevin Loughlin, Zheyun Shen, Peter Zijlstra,
Pawan Gupta, Xin Li, Ahmed S . Darwish, Sohil Mehta,
Ilkka Koskinen, Robin Murphy, James Clark, Besar Wicaksono, Ma Ke,
Wei Huang, Andy Gospodarek, Somnath Kotur, punit.agrawal,
guohanjun, suzuki.poulose, ryan.roberts, chenl311, masahiroy,
wangyuquan1236, anshuman.khandual, heinrich.schuchardt,
Eric.VanTassell, wangzhou1, wanghuiqiang, liuyonglong,
fengchengwen, linux-pci, linux-doc, linux-kernel,
linux-arm-kernel, loongarch, linux-riscv, xen-devel, linux-acpi,
linux-perf-users, stable
In-Reply-To: <20260320031737.35048-1-fengchengwen@huawei.com>
Centralize acpi_get_cpu_uid() in include/linux/acpi.h (global scope) and
remove arch-specific declarations from arm64/loongarch/riscv/x86
asm/acpi.h. This unifies the interface across architectures and
simplifies maintenance by eliminating duplicate prototypes.
Cc: stable@vger.kernel.org
Signed-off-by: Chengwen Feng <fengchengwen@huawei.com>
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
---
arch/arm64/include/asm/acpi.h | 1 -
arch/loongarch/include/asm/acpi.h | 1 -
arch/riscv/include/asm/acpi.h | 1 -
arch/x86/include/asm/acpi.h | 2 --
include/linux/acpi.h | 11 +++++++++++
5 files changed, 11 insertions(+), 5 deletions(-)
diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h
index 2219a3301e72..bdb0ecf95b5c 100644
--- a/arch/arm64/include/asm/acpi.h
+++ b/arch/arm64/include/asm/acpi.h
@@ -118,7 +118,6 @@ static inline u32 get_acpi_id_for_cpu(unsigned int cpu)
{
return acpi_cpu_get_madt_gicc(cpu)->uid;
}
-int acpi_get_cpu_uid(unsigned int cpu, u32 *uid);
int get_cpu_for_acpi_id(u32 uid);
static inline void arch_fix_phys_package_id(int num, u32 slot) { }
diff --git a/arch/loongarch/include/asm/acpi.h b/arch/loongarch/include/asm/acpi.h
index 8bb101b4557e..7376840fa9f7 100644
--- a/arch/loongarch/include/asm/acpi.h
+++ b/arch/loongarch/include/asm/acpi.h
@@ -44,7 +44,6 @@ static inline u32 get_acpi_id_for_cpu(unsigned int cpu)
{
return acpi_core_pic[cpu_logical_map(cpu)].processor_id;
}
-int acpi_get_cpu_uid(unsigned int cpu, u32 *uid);
#endif /* !CONFIG_ACPI */
diff --git a/arch/riscv/include/asm/acpi.h b/arch/riscv/include/asm/acpi.h
index f3520cc85af3..6e13695120bc 100644
--- a/arch/riscv/include/asm/acpi.h
+++ b/arch/riscv/include/asm/acpi.h
@@ -65,7 +65,6 @@ static inline u32 get_acpi_id_for_cpu(int cpu)
{
return acpi_cpu_get_madt_rintc(cpu)->uid;
}
-int acpi_get_cpu_uid(unsigned int cpu, u32 *uid);
int acpi_get_riscv_isa(struct acpi_table_header *table,
unsigned int cpu, const char **isa);
diff --git a/arch/x86/include/asm/acpi.h b/arch/x86/include/asm/acpi.h
index 92b5c27c4fea..a03aa6f999d1 100644
--- a/arch/x86/include/asm/acpi.h
+++ b/arch/x86/include/asm/acpi.h
@@ -157,8 +157,6 @@ static inline bool acpi_has_cpu_in_madt(void)
return !!acpi_lapic;
}
-int acpi_get_cpu_uid(unsigned int cpu, u32 *uid);
-
#define ACPI_HAVE_ARCH_SET_ROOT_POINTER
static __always_inline void acpi_arch_set_root_pointer(u64 addr)
{
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 4d2f0bed7a06..74a73f0e5944 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -324,6 +324,17 @@ int acpi_unmap_cpu(int cpu);
acpi_handle acpi_get_processor_handle(int cpu);
+/**
+ * acpi_get_cpu_uid() - Get ACPI Processor UID of from MADT table
+ * @cpu: Logical CPU number (0-based)
+ * @uid: Pointer to store ACPI Processor UID
+ *
+ * Return: 0 on success (ACPI Processor ID stored in *uid);
+ * -EINVAL if CPU number is invalid or out of range;
+ * -ENODEV if ACPI Processor UID for the CPU is not found.
+ */
+int acpi_get_cpu_uid(unsigned int cpu, u32 *uid);
+
#ifdef CONFIG_ACPI_HOTPLUG_IOAPIC
int acpi_get_ioapic_id(acpi_handle handle, u32 gsi_base, u64 *phys_addr);
#endif
--
2.17.1
^ permalink raw reply related
* [PATCH v10 0/8] ACPI: Unify CPU UID interface and fix ARM64 TPH steer-tag issue
From: Chengwen Feng @ 2026-03-20 3:17 UTC (permalink / raw)
To: Bjorn Helgaas, Catalin Marinas, Will Deacon, Rafael J . Wysocki
Cc: Jonathan Corbet, Palmer Dabbelt, Borislav Petkov, H . Peter Anvin,
Juergen Gross, Boris Ostrovsky, Len Brown, Sunil V L,
Mark Rutland, Jonathan Cameron, Kees Cook, Yanteng Si,
Sean Christopherson, Kai Huang, Tom Lendacky, Thomas Huth,
Thorsten Blum, Kevin Loughlin, Zheyun Shen, Peter Zijlstra,
Pawan Gupta, Xin Li, Ahmed S . Darwish, Sohil Mehta,
Ilkka Koskinen, Robin Murphy, James Clark, Besar Wicaksono, Ma Ke,
Wei Huang, Andy Gospodarek, Somnath Kotur, punit.agrawal,
guohanjun, suzuki.poulose, ryan.roberts, chenl311, masahiroy,
wangyuquan1236, anshuman.khandual, heinrich.schuchardt,
Eric.VanTassell, wangzhou1, wanghuiqiang, liuyonglong,
fengchengwen, linux-pci, linux-doc, linux-kernel,
linux-arm-kernel, loongarch, linux-riscv, xen-devel, linux-acpi,
linux-perf-users, stable
This patchset unifies ACPI Processor UID retrieval across
arm64/loongarch/riscv/x86 via acpi_get_cpu_uid() (with input validation)
and fixes ARM64 CPU steer-tag retrieval failure in PCI/TPH:
1-4: Add acpi_get_cpu_uid() for arm64/loongarch/riscv/x86 (update
respective users)
5: Centralize acpi_get_cpu_uid() declaration in include/linux/acpi.h
6: Clean up perf/arm_cspmu
7: Clean up ACPI/PPTT and remove unused get_acpi_id_for_cpu()
8: Pass ACPI Processor UID to Cache Locality _DSM
The interface refactor ensures consistent CPU UID retrieval across
architectures (no functional changes for valid inputs) and provides the
unified interface required for the ARM64 TPH fix.
---
Changes in v10:
- Refine commit header&log according to Punit's and Bjorn's review
- Split perf/arm_cspmu as a separate commit which address Punit's
review
Changes in v9:
- Address Bjorn's review: split commits to each platform so that make
them easy to review
Changes in v8:
- Moving arm64's get_cpu_for_acpi_id() to kernel/acpi.c which address
Jeremy's review
Chengwen Feng (8):
arm64: acpi: Add acpi_get_cpu_uid() for unified ACPI CPU UID retrieval
LoongArch: Add acpi_get_cpu_uid() for unified ACPI CPU UID retrieval
RISC-V: ACPI: Add acpi_get_cpu_uid() for unified ACPI CPU UID
retrieval
x86/acpi: Add acpi_get_cpu_uid() for unified ACPI CPU UID retrieval
ACPI: Centralize acpi_get_cpu_uid() declaration in
include/linux/acpi.h
perf: arm_cspmu: Switch to acpi_get_cpu_uid() from
get_acpi_id_for_cpu()
ACPI: PPTT: Use acpi_get_cpu_uid() and remove get_acpi_id_for_cpu()
PCI/TPH: Pass ACPI Processor UID to Cache Locality _DSM
Documentation/PCI/tph.rst | 4 +--
arch/arm64/include/asm/acpi.h | 17 +---------
arch/arm64/kernel/acpi.c | 30 ++++++++++++++++++
arch/loongarch/include/asm/acpi.h | 5 ---
arch/loongarch/kernel/acpi.c | 9 ++++++
arch/riscv/include/asm/acpi.h | 4 ---
arch/riscv/kernel/acpi.c | 16 ++++++++++
arch/riscv/kernel/acpi_numa.c | 9 ++++--
arch/x86/include/asm/cpu.h | 1 -
arch/x86/include/asm/smp.h | 1 -
arch/x86/kernel/acpi/boot.c | 20 ++++++++++++
arch/x86/xen/enlighten_hvm.c | 5 +--
drivers/acpi/pptt.c | 50 ++++++++++++++++++++++--------
drivers/acpi/riscv/rhct.c | 7 ++++-
drivers/pci/tph.c | 16 +++++++---
drivers/perf/arm_cspmu/arm_cspmu.c | 6 ++--
include/linux/acpi.h | 11 +++++++
include/linux/pci-tph.h | 4 +--
18 files changed, 158 insertions(+), 57 deletions(-)
--
2.17.1
^ permalink raw reply
* [PATCH v10 3/8] RISC-V: ACPI: Add acpi_get_cpu_uid() for unified ACPI CPU UID retrieval
From: Chengwen Feng @ 2026-03-20 3:17 UTC (permalink / raw)
To: Bjorn Helgaas, Catalin Marinas, Will Deacon, Rafael J . Wysocki
Cc: Jonathan Corbet, Palmer Dabbelt, Borislav Petkov, H . Peter Anvin,
Juergen Gross, Boris Ostrovsky, Len Brown, Sunil V L,
Mark Rutland, Jonathan Cameron, Kees Cook, Yanteng Si,
Sean Christopherson, Kai Huang, Tom Lendacky, Thomas Huth,
Thorsten Blum, Kevin Loughlin, Zheyun Shen, Peter Zijlstra,
Pawan Gupta, Xin Li, Ahmed S . Darwish, Sohil Mehta,
Ilkka Koskinen, Robin Murphy, James Clark, Besar Wicaksono, Ma Ke,
Wei Huang, Andy Gospodarek, Somnath Kotur, punit.agrawal,
guohanjun, suzuki.poulose, ryan.roberts, chenl311, masahiroy,
wangyuquan1236, anshuman.khandual, heinrich.schuchardt,
Eric.VanTassell, wangzhou1, wanghuiqiang, liuyonglong,
fengchengwen, linux-pci, linux-doc, linux-kernel,
linux-arm-kernel, loongarch, linux-riscv, xen-devel, linux-acpi,
linux-perf-users, stable
In-Reply-To: <20260320031737.35048-1-fengchengwen@huawei.com>
As a step towards unifying the interface for retrieving ACPI CPU UID
across architectures, introduce a new function acpi_get_cpu_uid() for
riscv. While at it, add input validation to make the code more robust.
And also update acpi_numa.c and rhct.c to use the new interface instead
of the legacy get_acpi_id_for_cpu().
Cc: stable@vger.kernel.org
Signed-off-by: Chengwen Feng <fengchengwen@huawei.com>
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
---
arch/riscv/include/asm/acpi.h | 1 +
arch/riscv/kernel/acpi.c | 16 ++++++++++++++++
arch/riscv/kernel/acpi_numa.c | 9 ++++++---
drivers/acpi/riscv/rhct.c | 7 ++++++-
4 files changed, 29 insertions(+), 4 deletions(-)
diff --git a/arch/riscv/include/asm/acpi.h b/arch/riscv/include/asm/acpi.h
index 6e13695120bc..f3520cc85af3 100644
--- a/arch/riscv/include/asm/acpi.h
+++ b/arch/riscv/include/asm/acpi.h
@@ -65,6 +65,7 @@ static inline u32 get_acpi_id_for_cpu(int cpu)
{
return acpi_cpu_get_madt_rintc(cpu)->uid;
}
+int acpi_get_cpu_uid(unsigned int cpu, u32 *uid);
int acpi_get_riscv_isa(struct acpi_table_header *table,
unsigned int cpu, const char **isa);
diff --git a/arch/riscv/kernel/acpi.c b/arch/riscv/kernel/acpi.c
index 71698ee11621..322ea92aa39f 100644
--- a/arch/riscv/kernel/acpi.c
+++ b/arch/riscv/kernel/acpi.c
@@ -337,3 +337,19 @@ int raw_pci_write(unsigned int domain, unsigned int bus,
}
#endif /* CONFIG_PCI */
+
+int acpi_get_cpu_uid(unsigned int cpu, u32 *uid)
+{
+ struct acpi_madt_rintc *rintc;
+
+ if (cpu >= nr_cpu_ids)
+ return -EINVAL;
+
+ rintc = acpi_cpu_get_madt_rintc(cpu);
+ if (!rintc)
+ return -ENODEV;
+
+ *uid = rintc->uid;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(acpi_get_cpu_uid);
diff --git a/arch/riscv/kernel/acpi_numa.c b/arch/riscv/kernel/acpi_numa.c
index 130769e3a99c..6a2d4289f806 100644
--- a/arch/riscv/kernel/acpi_numa.c
+++ b/arch/riscv/kernel/acpi_numa.c
@@ -37,11 +37,14 @@ static int __init acpi_numa_get_nid(unsigned int cpu)
static inline int get_cpu_for_acpi_id(u32 uid)
{
- int cpu;
+ u32 cpu_uid;
+ int ret;
- for (cpu = 0; cpu < nr_cpu_ids; cpu++)
- if (uid == get_acpi_id_for_cpu(cpu))
+ for (int cpu = 0; cpu < nr_cpu_ids; cpu++) {
+ ret = acpi_get_cpu_uid(cpu, &cpu_uid);
+ if (ret == 0 && uid == cpu_uid)
return cpu;
+ }
return -EINVAL;
}
diff --git a/drivers/acpi/riscv/rhct.c b/drivers/acpi/riscv/rhct.c
index caa2c16e1697..8f3f38c64a88 100644
--- a/drivers/acpi/riscv/rhct.c
+++ b/drivers/acpi/riscv/rhct.c
@@ -44,10 +44,15 @@ int acpi_get_riscv_isa(struct acpi_table_header *table, unsigned int cpu, const
struct acpi_rhct_isa_string *isa_node;
struct acpi_table_rhct *rhct;
u32 *hart_info_node_offset;
- u32 acpi_cpu_id = get_acpi_id_for_cpu(cpu);
+ u32 acpi_cpu_id;
+ int ret;
BUG_ON(acpi_disabled);
+ ret = acpi_get_cpu_uid(cpu, &acpi_cpu_id);
+ if (ret != 0)
+ return ret;
+
if (!table) {
rhct = acpi_get_rhct();
if (!rhct)
--
2.17.1
^ permalink raw reply related
* [PATCH v10 2/8] LoongArch: Add acpi_get_cpu_uid() for unified ACPI CPU UID retrieval
From: Chengwen Feng @ 2026-03-20 3:17 UTC (permalink / raw)
To: Bjorn Helgaas, Catalin Marinas, Will Deacon, Rafael J . Wysocki
Cc: Jonathan Corbet, Palmer Dabbelt, Borislav Petkov, H . Peter Anvin,
Juergen Gross, Boris Ostrovsky, Len Brown, Sunil V L,
Mark Rutland, Jonathan Cameron, Kees Cook, Yanteng Si,
Sean Christopherson, Kai Huang, Tom Lendacky, Thomas Huth,
Thorsten Blum, Kevin Loughlin, Zheyun Shen, Peter Zijlstra,
Pawan Gupta, Xin Li, Ahmed S . Darwish, Sohil Mehta,
Ilkka Koskinen, Robin Murphy, James Clark, Besar Wicaksono, Ma Ke,
Wei Huang, Andy Gospodarek, Somnath Kotur, punit.agrawal,
guohanjun, suzuki.poulose, ryan.roberts, chenl311, masahiroy,
wangyuquan1236, anshuman.khandual, heinrich.schuchardt,
Eric.VanTassell, wangzhou1, wanghuiqiang, liuyonglong,
fengchengwen, linux-pci, linux-doc, linux-kernel,
linux-arm-kernel, loongarch, linux-riscv, xen-devel, linux-acpi,
linux-perf-users, stable
In-Reply-To: <20260320031737.35048-1-fengchengwen@huawei.com>
As a step towards unifying the interface for retrieving ACPI CPU UID
across architectures, introduce a new function acpi_get_cpu_uid() for
loongarch. While at it, add input validation to make the code more
robust.
Cc: stable@vger.kernel.org
Signed-off-by: Chengwen Feng <fengchengwen@huawei.com>
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
---
arch/loongarch/include/asm/acpi.h | 1 +
arch/loongarch/kernel/acpi.c | 9 +++++++++
2 files changed, 10 insertions(+)
diff --git a/arch/loongarch/include/asm/acpi.h b/arch/loongarch/include/asm/acpi.h
index 7376840fa9f7..8bb101b4557e 100644
--- a/arch/loongarch/include/asm/acpi.h
+++ b/arch/loongarch/include/asm/acpi.h
@@ -44,6 +44,7 @@ static inline u32 get_acpi_id_for_cpu(unsigned int cpu)
{
return acpi_core_pic[cpu_logical_map(cpu)].processor_id;
}
+int acpi_get_cpu_uid(unsigned int cpu, u32 *uid);
#endif /* !CONFIG_ACPI */
diff --git a/arch/loongarch/kernel/acpi.c b/arch/loongarch/kernel/acpi.c
index 1367ca759468..058f0dbe8e8f 100644
--- a/arch/loongarch/kernel/acpi.c
+++ b/arch/loongarch/kernel/acpi.c
@@ -385,3 +385,12 @@ int acpi_unmap_cpu(int cpu)
EXPORT_SYMBOL(acpi_unmap_cpu);
#endif /* CONFIG_ACPI_HOTPLUG_CPU */
+
+int acpi_get_cpu_uid(unsigned int cpu, u32 *uid)
+{
+ if (cpu >= nr_cpu_ids)
+ return -EINVAL;
+ *uid = acpi_core_pic[cpu_logical_map(cpu)].processor_id;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(acpi_get_cpu_uid);
--
2.17.1
^ permalink raw reply related
* [PATCH v10 1/8] arm64: acpi: Add acpi_get_cpu_uid() for unified ACPI CPU UID retrieval
From: Chengwen Feng @ 2026-03-20 3:17 UTC (permalink / raw)
To: Bjorn Helgaas, Catalin Marinas, Will Deacon, Rafael J . Wysocki
Cc: Jonathan Corbet, Palmer Dabbelt, Borislav Petkov, H . Peter Anvin,
Juergen Gross, Boris Ostrovsky, Len Brown, Sunil V L,
Mark Rutland, Jonathan Cameron, Kees Cook, Yanteng Si,
Sean Christopherson, Kai Huang, Tom Lendacky, Thomas Huth,
Thorsten Blum, Kevin Loughlin, Zheyun Shen, Peter Zijlstra,
Pawan Gupta, Xin Li, Ahmed S . Darwish, Sohil Mehta,
Ilkka Koskinen, Robin Murphy, James Clark, Besar Wicaksono, Ma Ke,
Wei Huang, Andy Gospodarek, Somnath Kotur, punit.agrawal,
guohanjun, suzuki.poulose, ryan.roberts, chenl311, masahiroy,
wangyuquan1236, anshuman.khandual, heinrich.schuchardt,
Eric.VanTassell, wangzhou1, wanghuiqiang, liuyonglong,
fengchengwen, linux-pci, linux-doc, linux-kernel,
linux-arm-kernel, loongarch, linux-riscv, xen-devel, linux-acpi,
linux-perf-users, stable
In-Reply-To: <20260320031737.35048-1-fengchengwen@huawei.com>
As a step towards unifying the interface for retrieving ACPI CPU UID
across architectures, introduce a new function acpi_get_cpu_uid() for
arm64. While at it, add input validation to make the code more robust.
Reimplement get_cpu_for_acpi_id() based on acpi_get_cpu_uid() for
consistency, and move its implementation next to the new function for
code coherence.
Cc: stable@vger.kernel.org
Signed-off-by: Chengwen Feng <fengchengwen@huawei.com>
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
---
arch/arm64/include/asm/acpi.h | 14 ++------------
arch/arm64/kernel/acpi.c | 30 ++++++++++++++++++++++++++++++
2 files changed, 32 insertions(+), 12 deletions(-)
diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h
index c07a58b96329..2219a3301e72 100644
--- a/arch/arm64/include/asm/acpi.h
+++ b/arch/arm64/include/asm/acpi.h
@@ -118,18 +118,8 @@ static inline u32 get_acpi_id_for_cpu(unsigned int cpu)
{
return acpi_cpu_get_madt_gicc(cpu)->uid;
}
-
-static inline int get_cpu_for_acpi_id(u32 uid)
-{
- int cpu;
-
- for (cpu = 0; cpu < nr_cpu_ids; cpu++)
- if (acpi_cpu_get_madt_gicc(cpu) &&
- uid == get_acpi_id_for_cpu(cpu))
- return cpu;
-
- return -EINVAL;
-}
+int acpi_get_cpu_uid(unsigned int cpu, u32 *uid);
+int get_cpu_for_acpi_id(u32 uid);
static inline void arch_fix_phys_package_id(int num, u32 slot) { }
void __init acpi_init_cpus(void);
diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c
index af90128cfed5..24b9d934be54 100644
--- a/arch/arm64/kernel/acpi.c
+++ b/arch/arm64/kernel/acpi.c
@@ -458,3 +458,33 @@ int acpi_unmap_cpu(int cpu)
}
EXPORT_SYMBOL(acpi_unmap_cpu);
#endif /* CONFIG_ACPI_HOTPLUG_CPU */
+
+int acpi_get_cpu_uid(unsigned int cpu, u32 *uid)
+{
+ struct acpi_madt_generic_interrupt *gicc;
+
+ if (cpu >= nr_cpu_ids)
+ return -EINVAL;
+
+ gicc = acpi_cpu_get_madt_gicc(cpu);
+ if (!gicc)
+ return -ENODEV;
+
+ *uid = gicc->uid;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(acpi_get_cpu_uid);
+
+int get_cpu_for_acpi_id(u32 uid)
+{
+ u32 cpu_uid;
+ int ret;
+
+ for (int cpu = 0; cpu < nr_cpu_ids; cpu++) {
+ ret = acpi_get_cpu_uid(cpu, &cpu_uid);
+ if (ret == 0 && uid == cpu_uid)
+ return cpu;
+ }
+
+ return -EINVAL;
+}
--
2.17.1
^ permalink raw reply related
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