5.15.195-rc1 review
Subsystems (4)
Greg Kroah-Hartman
maintainerPATCH 146/276 s390/cio: Update purge function to unregister the unused subchannels
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vineeth Vijayan <[email protected]>
[ Upstream commit 9daa5a8795865f9a3c93d8d1066785b07ded6073 ]
Starting with 'commit 2297791c92d0 ("s390/cio: dont unregister subchannel from child-drivers")', cio no longer unregisters subchannels when the attached device is invalid or unavailable.
As an unintended side-effect, the cio_ignore purge function no longer removes subchannels for devices on the cio_ignore list if no CCW device is attached. This situation occurs when a CCW device is non-operational or unavailable
To ensure the same outcome of the purge function as when the current cio_ignore list had been active during boot, update the purge function to remove I/O subchannels without working CCW devices if the associated device number is found on the cio_ignore list.
--- drivers/s390/cio/device.c | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-)
drivers/s390/cio/device.c +24 -13
@@ -1323,23 +1323,34 @@ void ccw_device_schedule_recovery(void)spin_unlock_irqrestore (&recovery_lock, flags); } -static int purge_fn (struct device *dev,void *data) +static int purge_fn (struct subchannel *sch,void *data) { -struct ccw_device *cdev =to_ccwdev (dev); -struct ccw_dev_id *id = &cdev->private->dev_id; -struct subchannel *sch =to_subchannel (cdev->dev.parent); +struct ccw_device *cdev; -spin_lock_irq (cdev->ccwlock); -if (is_blacklisted (id->ssid, id->devno) && - (cdev->private->state ==DEV_STATE_OFFLINE ) && - (atomic_cmpxchg (&cdev->private->onoff,0 ,1 ) ==0 )) { -CIO_MSG_EVENT (3 ,"ccw: purging 0.%x.%04x\n" , id->ssid, - id->devno); +spin_lock_irq (&sch->lock); +if (sch->st !=SUBCHANNEL_TYPE_IO || !sch->schib.pmcw.dnv) + goto unlock; + +if (!is_blacklisted (sch->schid.ssid, sch->schib.pmcw.dev)) + goto unlock; + + cdev =sch_get_cdev (sch); +if (cdev) { +if (cdev->private->state !=DEV_STATE_OFFLINE ) + goto unlock; + +if (atomic_cmpxchg (&cdev->private->onoff,0 ,1 ) !=0 ) + goto unlock;ccw_device_sched_todo (cdev,CDEV_TODO_UNREG ); -css_sched_sch_todo (sch,SCH_TODO_UNREG );atomic_set (&cdev->private->onoff,0 ); } -spin_unlock_irq (cdev->ccwlock); + +css_sched_sch_todo (sch,SCH_TODO_UNREG ); +CIO_MSG_EVENT (3 ,"ccw: purging 0.%x.%04x%s\n" , sch->schid.ssid, + sch->schib.pmcw.dev, cdev ?"" :" (no cdev)" ); + +unlock: +spin_unlock_irq (&sch->lock);/* Abort loop in case of pending signal. */ if (signal_pending (current))return -EINTR ;
@@ -1355,7 +1366,7 @@ static int purge_fn(struct device *dev, void *data)int ccw_purge_blacklisted (void ) {CIO_MSG_EVENT (2 ,"ccw: purging blacklisted devices\n" ); -bus_for_each_dev (&ccw_bus_type,NULL ,NULL , purge_fn); +for_each_subchannel_staged (purge_fn,NULL ,NULL );return 0 ; }
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 147/276 drm/vmwgfx: Copy DRM hash-table code into driver
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thomas Zimmermann <[email protected]>
[ Upstream commit 2985c96485b7ef4e015d13dc3081fb0479260951 ]
Besides some legacy code, vmwgfx is the only user of DRM's hash- table implementation. Copy the code into the driver, so that the core code can be retired.
No functional changes. However, the real solution for vmwgfx is to use Linux' generic hash-table functions.
v2:
* add TODO item for updating vmwgfx (Sam)
Stable-dep-of: dfe1323ab3c8 ("drm/vmwgfx: Fix Use-after-free in validation")
--- Documentation/gpu/todo.rst | 11 ++ drivers/gpu/drm/vmwgfx/Makefile | 2 +- drivers/gpu/drm/vmwgfx/ttm_object.c | 52 +++--- drivers/gpu/drm/vmwgfx/ttm_object.h | 3 +- drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c | 24 +-- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 2 +- drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 6 +- drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c | 2 +- drivers/gpu/drm/vmwgfx/vmwgfx_hashtab.c | 199 +++++++++++++++++++++ drivers/gpu/drm/vmwgfx/vmwgfx_hashtab.h | 83 +++++++++ drivers/gpu/drm/vmwgfx/vmwgfx_validation.c | 22 +-- drivers/gpu/drm/vmwgfx/vmwgfx_validation.h | 7 +- 12 files changed, 353 insertions(+), 60 deletions(-) create mode 100644 drivers/gpu/drm/vmwgfx/vmwgfx_hashtab.c create mode 100644 drivers/gpu/drm/vmwgfx/vmwgfx_hashtab.h
Documentation/gpu/todo.rst +11 -0
@@ -635,6 +635,17 @@ See drivers/gpu/drm/amd/display/TODO for tasks. Contact: Harry Wentland, Alex Deucher +vmwgfx: Replace hashtable with Linux' implementation +---------------------------------------------------- + +The vmwgfx driver uses its own hashtable implementation. Replace the +code with Linux' implementation and update the callers. It's mostly a +refactoring task, but the interfaces are different. + +Contact: Zack Rusin, Thomas Zimmermann <[email protected]> + +Level: Intermediate + Bootsplash ==========
drivers/gpu/drm/vmwgfx/Makefile +1 -1
@@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 -vmwgfx-y := vmwgfx_execbuf.o vmwgfx_gmr.o vmwgfx_kms.o vmwgfx_drv.o \ +vmwgfx-y := vmwgfx_execbuf.o vmwgfx_gmr.o vmwgfx_hashtab.o vmwgfx_kms.o vmwgfx_drv.o \ vmwgfx_ioctl.o vmwgfx_resource.o vmwgfx_ttm_buffer.o \ vmwgfx_cmd.o vmwgfx_irq.o vmwgfx_ldu.o vmwgfx_ttm_glue.o \ vmwgfx_overlay.o vmwgfx_gmrid_manager.o vmwgfx_fence.o \
drivers/gpu/drm/vmwgfx/ttm_object.c +26 -26
165 lines not on this page · raw message
drivers/gpu/drm/vmwgfx/ttm_object.h +1 -2
@@ -42,9 +42,8 @@#include <linux/list.h> #include <linux/rcupdate.h> -#include <drm/drm_hashtab.h> -#include "ttm_memory.h" +#include "vmwgfx_hashtab.h" /** * enum ttm_ref_type
drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c +12 -12
@@ -42,7 +42,7 @@*/ struct vmw_cmdbuf_res {struct vmw_resource *res; -struct drm_hash_item hash; +struct vmwgfx_hash_item hash;struct list_head head;enum vmw_cmdbuf_res_state state;struct vmw_cmdbuf_res_manager *man;
@@ -59,7 +59,7 @@ struct vmw_cmdbuf_res {* @resources and @list are protected by the cmdbuf mutex for now. */ struct vmw_cmdbuf_res_manager { -struct drm_open_hash resources; +struct vmwgfx_open_hash resources;struct list_head list;struct vmw_private *dev_priv; };
@@ -81,11 +81,11 @@ vmw_cmdbuf_res_lookup(struct vmw_cmdbuf_res_manager *man, enum vmw_cmdbuf_res_type res_type, u32 user_key) { -struct drm_hash_item *hash; +struct vmwgfx_hash_item *hash;int ret;unsigned long key = user_key | (res_type <<24 ); - ret =drm_ht_find_item (&man->resources, key, &hash); + ret =vmwgfx_ht_find_item (&man->resources, key, &hash);if (unlikely (ret !=0 ))return ERR_PTR (ret);
@@ -105,7 +105,7 @@ static void vmw_cmdbuf_res_free(struct vmw_cmdbuf_res_manager *man, struct vmw_cmdbuf_res *entry) {list_del (&entry->head); -WARN_ON (drm_ht_remove_item (&man->resources, &entry->hash)); +WARN_ON (vmwgfx_ht_remove_item (&man->resources, &entry->hash));vmw_resource_unreference (&entry->res);kfree (entry); }
@@ -167,7 +167,7 @@ void vmw_cmdbuf_res_revert(struct list_head *list)vmw_cmdbuf_res_free (entry->man, entry);break ;case VMW_CMDBUF_RES_DEL : - ret =drm_ht_insert_item (&entry->man->resources, &entry->hash); + ret =vmwgfx_ht_insert_item (&entry->man->resources, &entry->hash);BUG_ON (ret);list_move_tail (&entry->head, &entry->man->list); entry->state =VMW_CMDBUF_RES_COMMITTED ;
@@ -206,7 +206,7 @@ int vmw_cmdbuf_res_add(struct vmw_cmdbuf_res_manager *man,return -ENOMEM ; cres->hash.key = user_key | (res_type <<24 ); - ret =drm_ht_insert_item (&man->resources, &cres->hash); + ret =vmwgfx_ht_insert_item (&man->resources, &cres->hash);if (unlikely (ret !=0 )) {kfree (cres); goto out_invalid_key;
@@ -244,10 +244,10 @@ int vmw_cmdbuf_res_remove(struct vmw_cmdbuf_res_manager *man, struct vmw_resource **res_p) {struct vmw_cmdbuf_res *entry; -struct drm_hash_item *hash; +struct vmwgfx_hash_item *hash;int ret; - ret =drm_ht_find_item (&man->resources, user_key | (res_type <<24 ), + ret =vmwgfx_ht_find_item (&man->resources, user_key | (res_type <<24 ), &hash);if (likely (ret !=0 ))return -EINVAL ;
@@ -260,7 +260,7 @@ int vmw_cmdbuf_res_remove(struct vmw_cmdbuf_res_manager *man, *res_p =NULL ;break ;case VMW_CMDBUF_RES_COMMITTED : - (void )drm_ht_remove_item (&man->resources, &entry->hash); + (void )vmwgfx_ht_remove_item (&man->resources, &entry->hash);list_del (&entry->head); entry->state =VMW_CMDBUF_RES_DEL ;list_add_tail (&entry->head, list);
@@ -295,7 +295,7 @@ vmw_cmdbuf_res_man_create(struct vmw_private *dev_priv) man->dev_priv = dev_priv;INIT_LIST_HEAD (&man->list); - ret =drm_ht_create (&man->resources,VMW_CMDBUF_RES_MAN_HT_ORDER ); + ret =vmwgfx_ht_create (&man->resources,VMW_CMDBUF_RES_MAN_HT_ORDER );if (ret ==0 )return man;
@@ -320,7 +320,7 @@ void vmw_cmdbuf_res_man_destroy(struct vmw_cmdbuf_res_manager *man)list_for_each_entry_safe (entry, next, &man->list, head)vmw_cmdbuf_res_free (man, entry); -drm_ht_remove (&man->resources); +vmwgfx_ht_remove (&man->resources);kfree (man); }
drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +1 -1
@@ -1149,7 +1149,7 @@ static void vmw_driver_unload(struct drm_device *dev)unregister_pm_notifier (&dev_priv->pm_nb);if (dev_priv->ctx.res_ht_initialized) -drm_ht_remove (&dev_priv->ctx.res_ht); +vmwgfx_ht_remove (&dev_priv->ctx.res_ht);vfree (dev_priv->ctx.cmd_bounce);if (dev_priv->enable_fb) {vmw_fb_off (dev_priv);
drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +3 -3
@@ -34,7 +34,6 @@#include <drm/drm_auth.h> #include <drm/drm_device.h> #include <drm/drm_file.h> -#include <drm/drm_hashtab.h> #include <drm/drm_rect.h> #include <drm/ttm/ttm_bo_driver.h>
@@ -43,6 +42,7 @@#include "ttm_object.h" #include "vmwgfx_fence.h" +#include "vmwgfx_hashtab.h" #include "vmwgfx_reg.h" #include "vmwgfx_validation.h"
@@ -131,7 +131,7 @@ struct vmw_buffer_object {*/ struct vmw_validate_buffer {struct ttm_validate_buffer base; -struct drm_hash_item hash; +struct vmwgfx_hash_item hash;bool validate_as_mob; };
@@ -404,7 +404,7 @@ struct vmw_ctx_validation_info;* @ctx: The validation context */ struct vmw_sw_context { -struct drm_open_hash res_ht; +struct vmwgfx_open_hash res_ht;bool res_ht_initialized;bool kernel;struct vmw_fpriv *fp;
drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +1 -1
@@ -4112,7 +4112,7 @@ int vmw_execbuf_process(struct drm_file *file_priv,vmw_binding_state_reset (sw_context->staged_bindings);if (!sw_context->res_ht_initialized) { - ret =drm_ht_create (&sw_context->res_ht,VMW_RES_HT_ORDER ); + ret =vmwgfx_ht_create (&sw_context->res_ht,VMW_RES_HT_ORDER );if (unlikely (ret !=0 )) goto out_unlock;
drivers/gpu/drm/vmwgfx/vmwgfx_hashtab.c new file +199 -0
199 lines not on this page · raw message
drivers/gpu/drm/vmwgfx/vmwgfx_hashtab.h new file +83 -0
83 lines not on this page · raw message
drivers/gpu/drm/vmwgfx/vmwgfx_validation.c +11 -11
@@ -43,7 +43,7 @@*/ struct vmw_validation_bo_node {struct ttm_validate_buffer base; -struct drm_hash_item hash; +struct vmwgfx_hash_item hash;unsigned int coherent_count;u32 as_mob :1 ;u32 cpu_blit :1 ;
@@ -72,7 +72,7 @@ struct vmw_validation_bo_node {*/ struct vmw_validation_res_node {struct list_head head; -struct drm_hash_item hash; +struct vmwgfx_hash_item hash;struct vmw_resource *res;struct vmw_buffer_object *new_backup;unsigned long new_backup_offset;
@@ -184,9 +184,9 @@ vmw_validation_find_bo_dup(struct vmw_validation_context *ctx,return NULL ;if (ctx->ht) { -struct drm_hash_item *hash; +struct vmwgfx_hash_item *hash; -if (!drm_ht_find_item (ctx->ht, (unsigned long ) vbo, &hash)) +if (!vmwgfx_ht_find_item (ctx->ht, (unsigned long ) vbo, &hash)) bo_node =container_of (hash,typeof (*bo_node), hash); }else {struct vmw_validation_bo_node *entry;
@@ -221,9 +221,9 @@ vmw_validation_find_res_dup(struct vmw_validation_context *ctx,return NULL ;if (ctx->ht) { -struct drm_hash_item *hash; +struct vmwgfx_hash_item *hash; -if (!drm_ht_find_item (ctx->ht, (unsigned long ) res, &hash)) +if (!vmwgfx_ht_find_item (ctx->ht, (unsigned long ) res, &hash)) res_node =container_of (hash,typeof (*res_node), hash); }else {struct vmw_validation_res_node *entry;
@@ -280,7 +280,7 @@ int vmw_validation_add_bo(struct vmw_validation_context *ctx,if (ctx->ht) { bo_node->hash.key = (unsigned long ) vbo; - ret =drm_ht_insert_item (ctx->ht, &bo_node->hash); + ret =vmwgfx_ht_insert_item (ctx->ht, &bo_node->hash);if (ret) {DRM_ERROR ("Failed to initialize a buffer " "validation entry.\n" );
@@ -335,7 +335,7 @@ int vmw_validation_add_resource(struct vmw_validation_context *ctx,if (ctx->ht) { node->hash.key = (unsigned long ) res; - ret =drm_ht_insert_item (ctx->ht, &node->hash); + ret =vmwgfx_ht_insert_item (ctx->ht, &node->hash);if (ret) {DRM_ERROR ("Failed to initialize a resource validation " "entry.\n" );
@@ -688,13 +688,13 @@ void vmw_validation_drop_ht(struct vmw_validation_context *ctx)return ;list_for_each_entry (entry, &ctx->bo_list, base.head) - (void )drm_ht_remove_item (ctx->ht, &entry->hash); + (void )vmwgfx_ht_remove_item (ctx->ht, &entry->hash);list_for_each_entry (val, &ctx->resource_list, head) - (void )drm_ht_remove_item (ctx->ht, &val->hash); + (void )vmwgfx_ht_remove_item (ctx->ht, &val->hash);list_for_each_entry (val, &ctx->resource_ctx_list, head) - (void )drm_ht_remove_item (ctx->ht, &val->hash); + (void )vmwgfx_ht_remove_item (ctx->ht, &val->hash); ctx->ht =NULL ; }
drivers/gpu/drm/vmwgfx/vmwgfx_validation.h +4 -3
@@ -31,9 +31,10 @@#include <linux/list.h> #include <linux/ww_mutex.h> -#include <drm/drm_hashtab.h> #include <drm/ttm/ttm_execbuf_util.h> +#include "vmwgfx_hashtab.h" +#define VMW_RES_DIRTY_NONE 0#define VMW_RES_DIRTY_SET BIT(0)#define VMW_RES_DIRTY_CLEAR BIT(1)
@@ -73,7 +74,7 @@ struct vmw_validation_mem {* @total_mem: Amount of reserved memory. */ struct vmw_validation_context { -struct drm_open_hash *ht; +struct vmwgfx_open_hash *ht;struct list_head resource_list;struct list_head resource_ctx_list;struct list_head bo_list;
@@ -151,7 +152,7 @@ vmw_validation_set_val_mem(struct vmw_validation_context *ctx,* available at validation context declaration time */ static inline void vmw_validation_set_ht (struct vmw_validation_context *ctx, -struct drm_open_hash *ht) +struct vmwgfx_open_hash *ht) { ctx->ht = ht; }
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 148/276 drm/vmwgfx: Fix Use-after-free in validation
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ian Forbes <[email protected]>
[ Upstream commit dfe1323ab3c8a4dd5625ebfdba44dc47df84512a ]
Nodes stored in the validation duplicates hashtable come from an arena allocator that is cleared at the end of vmw_execbuf_process. All nodes are expected to be cleared in vmw_validation_drop_ht but this node escaped because its resource was destroyed prematurely.
--- drivers/gpu/drm/vmwgfx/vmwgfx_validation.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/gpu/drm/vmwgfx/vmwgfx_validation.c +3 -1
@@ -343,8 +343,10 @@ int vmw_validation_add_resource(struct vmw_validation_context *ctx, } } node->res =vmw_resource_reference_unless_doomed (res); -if (!node->res) +if (!node->res) { +hash_del_rcu (&node->hash.head);return -ESRCH ; + } node->first_usage =1 ;if (!res->dev_priv->has_mob) {
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 149/276 net/sctp: fix a null dereference in sctp_disposition sctp_sf_do_5_1D_ce()
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexandr Sapozhnikov <[email protected]>
[ Upstream commit 2f3119686ef50319490ccaec81a575973da98815 ]
If new_asoc->peer.adaptation_ind=0 and sctp_ulpevent_make_authkey=0 and sctp_ulpevent_make_authkey() returns 0, then the variable ai_ev remains zero and the zero will be dereferenced
in the sctp_ulpevent_free() function.
--- net/sctp/sm_statefuns.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
net/sctp/sm_statefuns.c +2 -1
@@ -880,7 +880,8 @@ enum sctp_disposition sctp_sf_do_5_1D_ce(struct net *net,return SCTP_DISPOSITION_CONSUME ; nomem_authev: -sctp_ulpevent_free (ai_ev); +if (ai_ev) +sctp_ulpevent_free (ai_ev); nomem_aiev:sctp_ulpevent_free (ev); nomem_ev:
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 150/276 tcp: Dont call reqsk_fastopen_remove() in tcp_conn_request().
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kuniyuki Iwashima <[email protected]>
[ Upstream commit 2e7cbbbe3d61c63606994b7ff73c72537afe2e1c ]
syzbot reported the splat below in tcp_conn_request(). [0]
If a listener is close()d while a TFO socket is being processed in tcp_conn_request(), inet_csk_reqsk_queue_add() does not set reqsk->sk and calls inet_child_forget(), which calls tcp_disconnect() for the TFO socket.
After the cited commit, tcp_disconnect() calls reqsk_fastopen_remove(), where reqsk_put() is called due to !reqsk->sk.
Then, reqsk_fastopen_remove() in tcp_conn_request() decrements the last req->rsk_refcnt and frees reqsk, and __reqsk_free() at the drop_and_free label causes the refcount underflow for the listener and double-free of the reqsk.
Let's remove reqsk_fastopen_remove() in tcp_conn_request().
Note that other callers make sure tp->fastopen_rsk is not NULL.
[0]:refcount_t: underflow; use-after-free.
WARNING: CPU: 12 PID: 5563 at lib/refcount.c:28 refcount_warn_saturate (lib/refcount.c:28) Modules linked in: CPU: 12 UID: 0 PID: 5563 Comm: syz-executor Not tainted syzkaller #0 PREEMPT(full) Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 07/12/2025 RIP: 0010:refcount_warn_saturate (lib/refcount.c:28) Code: ab e8 8e b4 98 ff 0f 0b c3 cc cc cc cc cc 80 3d a4 e4 d6 01 00 75 9c c6 05 9b e4 d6 01 01 48 c7 c7 e8 df fb ab e8 6a b4 98 ff <0f> 0b e9 03 5b 76 00 cc 80 3d 7d e4 d6 01 00 0f 85 74 ff ff ff c6 RSP: 0018:ffffa79fc0304a98 EFLAGS: 00010246 RAX: d83af4db1c6b3900 RBX: ffff9f65c7a69020 RCX: d83af4db1c6b3900 RDX: 0000000000000000 RSI: 00000000ffff7fff RDI: ffffffffac78a280 RBP: 000000009d781b60 R08: 0000000000007fff R09: ffffffffac6ca280 R10: 0000000000017ffd R11: 0000000000000004 R12: ffff9f65c7b4f100 R13: ffff9f65c7d23c00 R14: ffff9f65c7d26000 R15: ffff9f65c7a64ef8 FS: 00007f9f962176c0(0000) GS:ffff9f65fcf00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000200000000180 CR3: 000000000dbbe006 CR4: 0000000000372ef0 Call Trace: <IRQ> tcp_conn_request (./include/linux/refcount.h:400 ./include/linux/refcount.h:432 ./include/linux/refcount.h:450 ./include/net/sock.h:1965 ./include/net/request_sock.h:131 net/ipv4/tcp_input.c:7301) tcp_rcv_state_process (net/ipv4/tcp_input.c:6708) tcp_v6_do_rcv (net/ipv6/tcp_ipv6.c:1670) tcp_v6_rcv (net/ipv6/tcp_ipv6.c:1906) ip6_protocol_deliver_rcu (net/ipv6/ip6_input.c:438) ip6_input (net/ipv6/ip6_input.c:500) ipv6_rcv (net/ipv6/ip6_input.c:311) __netif_receive_skb (net/core/dev.c:6104) process_backlog (net/core/dev.c:6456) __napi_poll (net/core/dev.c:7506) net_rx_action (net/core/dev.c:7569 net/core/dev.c:7696) handle_softirqs (kernel/softirq.c:579) do_softirq (kernel/softirq.c:480) </IRQ>
--- net/ipv4/tcp_input.c | 1 - 1 file changed, 1 deletion(-)
net/ipv4/tcp_input.c +0 -1
@@ -7060,7 +7060,6 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops, &foc, TCP_SYNACK_FASTOPEN, skb);/* Add the child socket directly into the accept queue */ if (!inet_csk_reqsk_queue_add (sk, req, fastopen_sk)) { -reqsk_fastopen_remove (fastopen_sk, req, false);bh_unlock_sock (fastopen_sk);sock_put (fastopen_sk); goto drop_and_free;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 151/276 net: fsl_pq_mdio: Fix device node reference leak in fsl_pq_mdio_probe
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Erick Karanja <[email protected]>
[ Upstream commit 521405cb54cd2812bbb6dedd5afc14bca1e7e98a ]
Add missing of_node_put call to release device node tbi obtained via for_each_child_of_node.
--- drivers/net/ethernet/freescale/fsl_pq_mdio.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/net/ethernet/freescale/fsl_pq_mdio.c +2 -0
@@ -482,10 +482,12 @@ static int fsl_pq_mdio_probe(struct platform_device *pdev)"missing 'reg' property in node %pOF\n" , tbi); err = -EBUSY ; +of_node_put (tbi); goto error; }set_tbipa (*prop, pdev, data->get_tbipa, priv->map, &res); +of_node_put (tbi); } }
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 152/276 tools build: Align warning options with perf
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Leo Yan <[email protected]>
[ Upstream commit 53d067feb8c4f16d1f24ce3f4df4450bb18c555f ]
The feature test programs are built without enabling '-Wall -Werror' options. As a result, a feature may appear to be available, but later building in perf can fail with stricter checks.
Make the feature test program use the same warning options as perf.
--- tools/build/feature/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
tools/build/feature/Makefile +2 -2
@@ -268,10 +268,10 @@ $(OUTPUT)test-libbabeltrace.bin: $(BUILD) # -lbabeltrace provided by $(FEATURE_CHECK_LDFLAGS-libbabeltrace) $(OUTPUT)test-compile-32.bin: - $(CC) -m32 -o $@ test-compile.c + $(CC) -m32 -Wall -Werror -o $@ test-compile.c $(OUTPUT)test-compile-x32.bin: - $(CC) -mx32 -o $@ test-compile.c + $(CC) -mx32 -Wall -Werror -o $@ test-compile.c $(OUTPUT)test-zlib.bin: $(BUILD) -lz
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 153/276 mailbox: zynqmp-ipi: Remove redundant mbox_controller_unregister() call
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Harini T <[email protected]>
[ Upstream commit 341867f730d3d3bb54491ee64e8b1a0c446656e7 ]
The controller is registered using the device-managed function 'devm_mbox_controller_register()'. As documented in mailbox.c, this ensures the devres framework automatically calls mbox_controller_unregister() when device_unregister() is invoked, making the explicit call unnecessary.
Remove redundant mbox_controller_unregister() call as device_unregister() handles controller cleanup.
--- drivers/mailbox/zynqmp-ipi-mailbox.c | 1 - 1 file changed, 1 deletion(-)
drivers/mailbox/zynqmp-ipi-mailbox.c +0 -1
@@ -619,7 +619,6 @@ static void zynqmp_ipi_free_mboxes(struct zynqmp_ipi_pdata *pdata)for (; i >=0 ; i--) { ipi_mbox = &pdata->ipi_mboxes[i];if (ipi_mbox->dev.parent) { -mbox_controller_unregister (&ipi_mbox->mbox);if (device_is_registered (&ipi_mbox->dev))device_unregister (&ipi_mbox->dev); }
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 154/276 mailbox: zynqmp-ipi: Remove dev.parent check in zynqmp_ipi_free_mboxes
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Harini T <[email protected]>
[ Upstream commit 019e3f4550fc7d319a7fd03eff487255f8e8aecd ]
The ipi_mbox->dev.parent check is unreliable proxy for registration status as it fails to protect against probe failures that occur after the parent is assigned but before device_register() completes.
device_is_registered() is the canonical and robust method to verify the registration status.
Remove ipi_mbox->dev.parent check in zynqmp_ipi_free_mboxes().
--- drivers/mailbox/zynqmp-ipi-mailbox.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
drivers/mailbox/zynqmp-ipi-mailbox.c +2 -4
@@ -618,10 +618,8 @@ static void zynqmp_ipi_free_mboxes(struct zynqmp_ipi_pdata *pdata) i = pdata->num_mboxes;for (; i >=0 ; i--) { ipi_mbox = &pdata->ipi_mboxes[i]; -if (ipi_mbox->dev.parent) { -if (device_is_registered (&ipi_mbox->dev)) -device_unregister (&ipi_mbox->dev); - } +if (device_is_registered (&ipi_mbox->dev)) +device_unregister (&ipi_mbox->dev); } }
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 155/276 bpf: Fix metadata_dst leak __bpf_redirect_neigh_v{4,6}
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Daniel Borkmann <[email protected]>
[ Upstream commit 23f3770e1a53e6c7a553135011f547209e141e72 ]
Cilium has a BPF egress gateway feature which forces outgoing K8s Pod traffic to pass through dedicated egress gateways which then SNAT the traffic in order to interact with stable IPs outside the cluster.
The traffic is directed to the gateway via vxlan tunnel in collect md mode. A recent BPF change utilized the bpf_redirect_neigh() helper to forward packets after the arrival and decap on vxlan, which turned out over time that the kmalloc-256 slab usage in kernel was ever-increasing.
The issue was that vxlan allocates the metadata_dst object and attaches it through a fake dst entry to the skb. The latter was never released though given bpf_redirect_neigh() was merely setting the new dst entry via skb_dst_set() without dropping an existing one first.
--- net/core/filter.c | 2 ++ 1 file changed, 2 insertions(+)
net/core/filter.c +2 -0
@@ -2257,6 +2257,7 @@ static int __bpf_redirect_neigh_v6(struct sk_buff *skb, struct net_device *dev,if (IS_ERR (dst)) goto out_drop; +skb_dst_drop (skb);skb_dst_set (skb, dst); }else if (nh->nh_family !=AF_INET6 ) { goto out_drop;
@@ -2364,6 +2365,7 @@ static int __bpf_redirect_neigh_v4(struct sk_buff *skb, struct net_device *dev, goto out_drop; } +skb_dst_drop (skb);skb_dst_set (skb, &rt->dst); }
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 156/276 drm/amdgpu: Add additional DCE6 SCL registers
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Deucher <[email protected]>
[ Upstream commit 507296328b36ffd00ec1f4fde5b8acafb7222ec7 ]
--- drivers/gpu/drm/amd/include/asic_reg/dce/dce_6_0_d.h | 7 +++++++ drivers/gpu/drm/amd/include/asic_reg/dce/dce_6_0_sh_mask.h | 2 ++ 2 files changed, 9 insertions(+)
drivers/gpu/drm/amd/include/asic_reg/dce/dce_6_0_d.h +7 -0
@@ -4115,6 +4115,7 @@#define mmSCL0_SCL_COEF_RAM_CONFLICT_STATUS 0x1B55#define mmSCL0_SCL_COEF_RAM_SELECT 0x1B40#define mmSCL0_SCL_COEF_RAM_TAP_DATA 0x1B41 +#define mmSCL0_SCL_SCALER_ENABLE 0x1B42#define mmSCL0_SCL_CONTROL 0x1B44#define mmSCL0_SCL_DEBUG 0x1B6A#define mmSCL0_SCL_DEBUG2 0x1B69
@@ -4144,6 +4145,7 @@#define mmSCL1_SCL_COEF_RAM_CONFLICT_STATUS 0x1E55#define mmSCL1_SCL_COEF_RAM_SELECT 0x1E40#define mmSCL1_SCL_COEF_RAM_TAP_DATA 0x1E41 +#define mmSCL1_SCL_SCALER_ENABLE 0x1E42#define mmSCL1_SCL_CONTROL 0x1E44#define mmSCL1_SCL_DEBUG 0x1E6A#define mmSCL1_SCL_DEBUG2 0x1E69
@@ -4173,6 +4175,7 @@#define mmSCL2_SCL_COEF_RAM_CONFLICT_STATUS 0x4155#define mmSCL2_SCL_COEF_RAM_SELECT 0x4140#define mmSCL2_SCL_COEF_RAM_TAP_DATA 0x4141 +#define mmSCL2_SCL_SCALER_ENABLE 0x4142#define mmSCL2_SCL_CONTROL 0x4144#define mmSCL2_SCL_DEBUG 0x416A#define mmSCL2_SCL_DEBUG2 0x4169
@@ -4202,6 +4205,7 @@#define mmSCL3_SCL_COEF_RAM_CONFLICT_STATUS 0x4455#define mmSCL3_SCL_COEF_RAM_SELECT 0x4440#define mmSCL3_SCL_COEF_RAM_TAP_DATA 0x4441 +#define mmSCL3_SCL_SCALER_ENABLE 0x4442#define mmSCL3_SCL_CONTROL 0x4444#define mmSCL3_SCL_DEBUG 0x446A#define mmSCL3_SCL_DEBUG2 0x4469
@@ -4231,6 +4235,7 @@#define mmSCL4_SCL_COEF_RAM_CONFLICT_STATUS 0x4755#define mmSCL4_SCL_COEF_RAM_SELECT 0x4740#define mmSCL4_SCL_COEF_RAM_TAP_DATA 0x4741 +#define mmSCL4_SCL_SCALER_ENABLE 0x4742#define mmSCL4_SCL_CONTROL 0x4744#define mmSCL4_SCL_DEBUG 0x476A#define mmSCL4_SCL_DEBUG2 0x4769
@@ -4260,6 +4265,7 @@#define mmSCL5_SCL_COEF_RAM_CONFLICT_STATUS 0x4A55#define mmSCL5_SCL_COEF_RAM_SELECT 0x4A40#define mmSCL5_SCL_COEF_RAM_TAP_DATA 0x4A41 +#define mmSCL5_SCL_SCALER_ENABLE 0x4A42#define mmSCL5_SCL_CONTROL 0x4A44#define mmSCL5_SCL_DEBUG 0x4A6A#define mmSCL5_SCL_DEBUG2 0x4A69
@@ -4287,6 +4293,7 @@#define mmSCL_COEF_RAM_CONFLICT_STATUS 0x1B55#define mmSCL_COEF_RAM_SELECT 0x1B40#define mmSCL_COEF_RAM_TAP_DATA 0x1B41 +#define mmSCL_SCALER_ENABLE 0x1B42#define mmSCL_CONTROL 0x1B44#define mmSCL_DEBUG 0x1B6A#define mmSCL_DEBUG2 0x1B69
drivers/gpu/drm/amd/include/asic_reg/dce/dce_6_0_sh_mask.h +2 -0
@@ -8646,6 +8646,8 @@#define REGAMMA_LUT_INDEX__REGAMMA_LUT_INDEX__SHIFT 0x00000000#define REGAMMA_LUT_WRITE_EN_MASK__REGAMMA_LUT_WRITE_EN_MASK_MASK 0x00000007L#define REGAMMA_LUT_WRITE_EN_MASK__REGAMMA_LUT_WRITE_EN_MASK__SHIFT 0x00000000 +#define SCL_SCALER_ENABLE__SCL_SCALE_EN_MASK 0x00000001L +#define SCL_SCALER_ENABLE__SCL_SCALE_EN__SHIFT 0x00000000#define SCL_ALU_CONTROL__SCL_ALU_DISABLE_MASK 0x00000001L#define SCL_ALU_CONTROL__SCL_ALU_DISABLE__SHIFT 0x00000000#define SCL_BYPASS_CONTROL__SCL_BYPASS_MODE_MASK 0x00000003L
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 157/276 drm/amd/display: Add missing DCE6 SCL_HORZ_FILTER_INIT* SRIs
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Timur Kristóf <[email protected]>
[ Upstream commit d60f9c45d1bff7e20ecd57492ef7a5e33c94a37c ]
Without these, it's impossible to program these registers.
--- drivers/gpu/drm/amd/display/dc/dce/dce_transform.h | 2 ++ 1 file changed, 2 insertions(+)
drivers/gpu/drm/amd/display/dc/dce/dce_transform.h +2 -0
@@ -155,6 +155,8 @@SRI (SCL_COEF_RAM_TAP_DATA ,SCL , id), \SRI (VIEWPORT_START ,SCL , id), \SRI (VIEWPORT_SIZE ,SCL , id), \ +SRI (SCL_HORZ_FILTER_INIT_RGB_LUMA ,SCL , id), \ +SRI (SCL_HORZ_FILTER_INIT_CHROMA ,SCL , id), \SRI (SCL_HORZ_FILTER_SCALE_RATIO ,SCL , id), \SRI (SCL_VERT_FILTER_SCALE_RATIO ,SCL , id), \ SRI(SCL_VERT_FILTER_INIT, SCL, id), \
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 158/276 drm/amd/display: Properly clear SCL_*_FILTER_CONTROL on DCE6
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Timur Kristóf <[email protected]>
[ Upstream commit c0aa7cf49dd6cb302fe28e7183992b772cb7420c ]
Previously, the code would set a bit field which didn't exist on DCE6 so it would be effectively a no-op.
--- drivers/gpu/drm/amd/display/dc/dce/dce_transform.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
drivers/gpu/drm/amd/display/dc/dce/dce_transform.c +2 -4
@@ -527,8 +527,7 @@ static void dce60_transform_set_scaler(if (coeffs_v != xfm_dce->filter_v || coeffs_h != xfm_dce->filter_h) {/* 4. Program vertical filters */ if (xfm_dce->filter_v ==NULL ) -REG_SET (SCL_VERT_FILTER_CONTROL ,0 , -SCL_V_2TAP_HARDCODE_COEF_EN ,0 ); +REG_WRITE (SCL_VERT_FILTER_CONTROL ,0 ); program_multi_taps_filter( xfm_dce, data->taps.v_taps,
@@ -542,8 +541,7 @@ static void dce60_transform_set_scaler(/* 5. Program horizontal filters */ if (xfm_dce->filter_h ==NULL ) -REG_SET (SCL_HORZ_FILTER_CONTROL ,0 , -SCL_H_2TAP_HARDCODE_COEF_EN ,0 ); +REG_WRITE (SCL_HORZ_FILTER_CONTROL ,0 ); program_multi_taps_filter( xfm_dce, data->taps.h_taps,
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 159/276 drm/amd/display: Properly disable scaling on DCE6
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Timur Kristóf <[email protected]>
[ Upstream commit a7dc87f3448bea5ebe054f14e861074b9c289c65 ]
SCL_SCALER_ENABLE can be used to enable/disable the scaler on DCE6. Program it to 0 when scaling isn't used, 1 when used. Additionally, clear some other registers when scaling is disabled and program the SCL_UPDATE register as recommended.
This fixes visible glitches for users whose BIOS sets up a mode with scaling at boot, which DC was unable to clean up.
--- .../gpu/drm/amd/display/dc/dce/dce_transform.c | 15 +++++++++++---- .../gpu/drm/amd/display/dc/dce/dce_transform.h | 2 ++ 2 files changed, 13 insertions(+), 4 deletions(-)
drivers/gpu/drm/amd/display/dc/dce/dce_transform.c +11 -4
@@ -154,10 +154,13 @@ static bool dce60_setup_scaling_configuration(REG_SET (SCL_BYPASS_CONTROL ,0 ,SCL_BYPASS_MODE ,0 );if (data->taps.h_taps + data->taps.v_taps <=2 ) { -/* Set bypass */ - -/* DCE6 has no SCL_MODE register, skip scale mode programming */ +/* Disable scaler functionality */ +REG_WRITE (SCL_SCALER_ENABLE ,0 ); +/* Clear registers that can cause glitches even when the scaler is off */ +REG_WRITE (SCL_TAP_CONTROL ,0 ); +REG_WRITE (SCL_AUTOMATIC_MODE_CONTROL ,0 ); +REG_WRITE (SCL_F_SHARP_CONTROL ,0 );return false; }
@@ -165,7 +168,7 @@ static bool dce60_setup_scaling_configuration(SCL_H_NUM_OF_TAPS , data->taps.h_taps -1 , SCL_V_NUM_OF_TAPS, data->taps.v_taps - 1); -/* DCE6 has no SCL_MODE register, skip scale mode programming */ +REG_WRITE (SCL_SCALER_ENABLE ,1 );/* DCE6 has no SCL_BOUNDARY_MODE bit, skip replace out of bound pixels */
@@ -502,6 +505,8 @@ static void dce60_transform_set_scaler(REG_SET (DC_LB_MEM_SIZE ,0 ,DC_LB_MEM_SIZE , xfm_dce->lb_memory_size); +REG_WRITE (SCL_UPDATE ,0x00010000 ); +/* Clear SCL_F_SHARP_CONTROL value to 0 */ REG_WRITE (SCL_F_SHARP_CONTROL ,0 );
@@ -564,6 +569,8 @@ static void dce60_transform_set_scaler(/* DCE6 has no SCL_COEF_UPDATE_COMPLETE bit to flip to new coefficient memory */ /* DCE6 DATA_FORMAT register does not support ALPHA_EN */ + + REG_WRITE(SCL_UPDATE, 0); }#endif
drivers/gpu/drm/amd/display/dc/dce/dce_transform.h +2 -0
@@ -155,6 +155,7 @@SRI (SCL_COEF_RAM_TAP_DATA ,SCL , id), \SRI (VIEWPORT_START ,SCL , id), \SRI (VIEWPORT_SIZE ,SCL , id), \ +SRI (SCL_SCALER_ENABLE ,SCL , id), \SRI (SCL_HORZ_FILTER_INIT_RGB_LUMA ,SCL , id), \SRI (SCL_HORZ_FILTER_INIT_CHROMA ,SCL , id), \ SRI(SCL_HORZ_FILTER_SCALE_RATIO, SCL, id), \
@@ -592,6 +593,7 @@ struct dce_transform_registers {uint32_t SCL_VERT_FILTER_SCALE_RATIO ;uint32_t SCL_HORZ_FILTER_INIT ;#if defined(CONFIG_DRM_AMD_DC_SI ) +uint32_t SCL_SCALER_ENABLE ;uint32_t SCL_HORZ_FILTER_INIT_RGB_LUMA ;uint32_t SCL_HORZ_FILTER_INIT_CHROMA ;#endif
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 160/276 bridge: br_vlan_fill_forward_path_pvid: use br_vlan_group_rcu()
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Woudstra <[email protected]>
[ Upstream commit bbf0c98b3ad9edaea1f982de6c199cc11d3b7705 ]
net/bridge/br_private.h:1627 suspicious rcu_dereference_protected() usage! other info that might help us debug this:
rcu_scheduler_active = 2, debug_locks = 1
7 locks held by socat/410:
#0: ffff88800d7a9c90 (sk_lock-AF_INET){+.+.}-{0:0}, at: inet_stream_connect+0x43/0xa0 #1: ffffffff9a779900 (rcu_read_lock){....}-{1:3}, at: __ip_queue_xmit+0x62/0x1830 [..]
#6: ffffffff9a779900 (rcu_read_lock){....}-{1:3}, at: nf_hook.constprop.0+0x8a/0x440
Call Trace: lockdep_rcu_suspicious.cold+0x4f/0xb1 br_vlan_fill_forward_path_pvid+0x32c/0x410 [bridge] br_fill_forward_path+0x7a/0x4d0 [bridge]
Use to correct helper, non _rcu variant requires RTNL mutex.
--- net/bridge/br_vlan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/bridge/br_vlan.c +1 -1
@@ -1391,7 +1391,7 @@ void br_vlan_fill_forward_path_pvid(struct net_bridge *br,if (!br_opt_get (br,BROPT_VLAN_ENABLED ))return ; - vg =br_vlan_group (br); + vg =br_vlan_group_rcu (br);if (idx >=0 && ctx->vlan[idx].proto == br->vlan_proto) {
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 161/276 crypto: essiv - Check ssize for decryption and in-place encryption
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Herbert Xu <[email protected]>
[ Upstream commit 6bb73db6948c2de23e407fe1b7ef94bf02b7529f ]
Move the ssize check to the start in essiv_aead_crypt so that it's also checked for decryption and in-place encryption.
--- crypto/essiv.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-)
crypto/essiv.c +6 -8
@@ -186,9 +186,14 @@ static int essiv_aead_crypt(struct aead_request *req, bool enc)const struct essiv_tfm_ctx *tctx =crypto_aead_ctx (tfm);struct essiv_aead_request_ctx *rctx =aead_request_ctx (req);struct aead_request *subreq = &rctx->aead_req; +int ivsize =crypto_aead_ivsize (tfm); +int ssize = req->assoclen - ivsize;struct scatterlist *src = req->src;int err; +if (ssize <0 ) +return -EINVAL ; +crypto_cipher_encrypt_one (tctx->essiv_cipher, req->iv, req->iv);/*
@@ -198,19 +203,12 @@ static int essiv_aead_crypt(struct aead_request *req, bool enc)*/ rctx->assoc =NULL ;if (req->src == req->dst || !enc) { -scatterwalk_map_and_copy (req->iv, req->dst, - req->assoclen -crypto_aead_ivsize (tfm), -crypto_aead_ivsize (tfm),1 ); +scatterwalk_map_and_copy (req->iv, req->dst, ssize, ivsize,1 ); }else {u8 *iv = (u8 *)aead_request_ctx (req) + tctx->ivoffset; -int ivsize =crypto_aead_ivsize (tfm); -int ssize = req->assoclen - ivsize;struct scatterlist *sg;int nents; -if (ssize <0 ) -return -EINVAL ; - nents =sg_nents_for_len (req->src, ssize);if (nents <0 )return -EINVAL ;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 162/276 tpm_tis: Fix incorrect arguments in tpm_tis_probe_irq_single
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gunnar Kudrjavets <[email protected]>
[ Upstream commit 8a81236f2cb0882c7ea6c621ce357f7f3f601fe5 ]
The tpm_tis_write8() call specifies arguments in wrong order. Should be (data, addr, value) not (data, value, addr). The initial correct order was changed during the major refactoring when the code was split.
--- drivers/char/tpm/tpm_tis_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/char/tpm/tpm_tis_core.c +2 -2
@@ -831,8 +831,8 @@ static int tpm_tis_probe_irq_single(struct tpm_chip *chip, u32 intmask,* will call disable_irq which undoes all of the above. */ if (!(chip->flags &TPM_CHIP_FLAG_IRQ )) { -tpm_tis_write8 (priv, original_int_vec, -TPM_INT_VECTOR (priv->locality)); +tpm_tis_write8 (priv,TPM_INT_VECTOR (priv->locality), + original_int_vec); rc =-1 ; }
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 163/276 gpio: wcd934x: Remove duplicate assignment of of_gpio_n_cells
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andy Shevchenko <[email protected]>
[ Upstream commit a060dc6620c13435b78e92cd2ebdbb6d11af237a ]
The of_gpio_n_cells default is 2 when ->of_xlate() callback is not defined. No need to assign it explicitly in the driver.
Stable-dep-of: b5f8aa8d4bde ("gpio: wcd934x: mark the GPIO controller as sleeping")
--- drivers/gpio/gpio-wcd934x.c | 1 - 1 file changed, 1 deletion(-)
drivers/gpio/gpio-wcd934x.c +0 -1
@@ -101,7 +101,6 @@ static int wcd_gpio_probe(struct platform_device *pdev) chip->base =-1 ; chip->ngpio =WCD934X_NPINS ; chip->label =dev_name (dev); - chip->of_gpio_n_cells =2 ; chip->can_sleep = false;return devm_gpiochip_add_data (dev, chip, data);
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 164/276 gpio: wcd934x: mark the GPIO controller as sleeping
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bartosz Golaszewski <[email protected]>
[ Upstream commit b5f8aa8d4bde0cf3e4595af5a536da337e5f1c78 ]
The slimbus regmap passed to the GPIO driver down from MFD does not use fast_io. This means a mutex is used for locking and thus this GPIO chip must not be used in atomic context. Change the can_sleep switch in struct gpio_chip to true.
--- drivers/gpio/gpio-wcd934x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpio/gpio-wcd934x.c +1 -1
@@ -101,7 +101,7 @@ static int wcd_gpio_probe(struct platform_device *pdev) chip->base =-1 ; chip->ngpio =WCD934X_NPINS ; chip->label =dev_name (dev); - chip->can_sleep = false; + chip->can_sleep = true;return devm_gpiochip_add_data (dev, chip, data); }
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 165/276 bpf: Avoid RCU context warning when unpinning htab with internal structs
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: KaFai Wan <[email protected]>
[ Upstream commit 4f375ade6aa9f37fd72d7a78682f639772089eed ]
When unpinning a BPF hash table (htab or htab_lru) that contains internal structures (timer, workqueue, or task_work) in its values, a BUG warning is triggered:
BUG: sleeping function called from invalid context at kernel/bpf/hashtab.c:244 in_atomic(): 1, irqs_disabled(): 0, non_block: 0, pid: 14, name: ksoftirqd/0 ...
The issue arises from the interaction between BPF object unpinning and RCU callback mechanisms:
1. BPF object unpinning uses ->free_inode() which schedules cleanup via call_rcu(), deferring the actual freeing to an RCU callback that executes within the RCU_SOFTIRQ context.
2. During cleanup of hash tables containing internal structures, htab_map_free_internal_structs() is invoked, which includes cond_resched() or cond_resched_rcu() calls to yield the CPU during potentially long operations.
However, cond_resched() or cond_resched_rcu() cannot be safely called from atomic RCU softirq context, leading to the BUG warning when attempting to reschedule.
Fix this by changing from ->free_inode() to ->destroy_inode() and rename bpf_free_inode() to bpf_destroy_inode() for BPF objects (prog, map, link). This allows direct inode freeing without RCU callback scheduling, avoiding the invalid context warning.
--- kernel/bpf/inode.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
kernel/bpf/inode.c +2 -2
@@ -610,7 +610,7 @@ static int bpf_show_options(struct seq_file *m, struct dentry *root)return 0 ; } -static void bpf_free_inode (struct inode *inode) +static void bpf_destroy_inode (struct inode *inode) {enum bpf_type type;
@@ -625,7 +625,7 @@ static const struct super_operations bpf_super_ops = { .statfs = simple_statfs, .drop_inode = generic_delete_inode, .show_options = bpf_show_options, - .free_inode = bpf_free_inode, + .destroy_inode = bpf_destroy_inode, };enum {
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 166/276 ACPI: TAD: Add missing sysfs_remove_group() for ACPI_TAD_RT
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Daniel Tang <[email protected]>
commit 4aac453deca0d9c61df18d968f8864c3ae7d3d8d upstream.
Previously, after rmmod acpi_tad, modprobe acpi_tad would fail with this dmesg:
sysfs: cannot create duplicate filename '/devices/platform/ACPI000E:00/time'
Call Trace: <TASK> dump_stack_lvl+0x6c/0x90 dump_stack+0x10/0x20 sysfs_warn_dup+0x8b/0xa0 sysfs_add_file_mode_ns+0x122/0x130 internal_create_group+0x1dd/0x4c0 sysfs_create_group+0x13/0x20 acpi_tad_probe+0x147/0x1f0 [acpi_tad] platform_probe+0x42/0xb0 </TASK>
acpi-tad ACPI000E:00: probe with driver acpi-tad failed with error -17
--- drivers/acpi/acpi_tad.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/acpi/acpi_tad.c +3 -0
@@ -563,6 +563,9 @@ static int acpi_tad_remove(struct platfopm_runtime_get_sync (dev); +if (dd->capabilities &ACPI_TAD_RT ) +sysfs_remove_group (&dev->kobj, &acpi_tad_time_attr_group); +if (dd->capabilities &ACPI_TAD_DC_WAKE )sysfs_remove_group (&dev->kobj, &acpi_tad_dc_attr_group);
Greg Kroah-Hartman
maintainerPATCH 167/276 ACPI: debug: fix signedness issues in read/write helpers
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Amir Mohammad Jahangirzad <[email protected]>
commit 496f9372eae14775e0524e83e952814691fe850a upstream.
In the ACPI debugger interface, the helper functions for read and write operations use "int" as the length parameter data type. When a large "size_t count" is passed from the file operations, this cast to "int" results in truncation and a negative value due to signed integer representation.
Logically, this negative number propagates to the min() calculation, where it is selected over the positive buffer space value, leading to unexpected behavior. Subsequently, when this negative value is used in copy_to_user() or copy_from_user(), it is interpreted as a large positive value due to the unsigned nature of the size parameter in these functions, causing the copy operations to attempt handling sizes far beyond the intended buffer limits.
Address the issue by:
- Changing the length parameters in acpi_aml_read_user() and acpi_aml_write_user() from "int" to "size_t", aligning with the expected unsigned size semantics.
- Updating return types and local variables in acpi_aml_read() and acpi_aml_write() to "ssize_t" for consistency with kernel file operation conventions.
- Using "size_t" for the "n" variable to ensure calculations remain unsigned.
- Using min_t() for circ_count_to_end() and circ_space_to_end() to ensure type-safe comparisons and prevent integer overflow.
--- drivers/acpi/acpi_dbg.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-)
drivers/acpi/acpi_dbg.c +13 -13
@@ -569,11 +569,11 @@ static int acpi_aml_release(struct inodereturn 0 ; } -static int acpi_aml_read_user (char __user *buf,int len) +static ssize_t acpi_aml_read_user (char __user *buf,size_t len) { -int ret;struct circ_buf *crc = &acpi_aml_io.out_crc; -int n; +ssize_t ret; +size_t n;char *p; ret =acpi_aml_lock_read (crc,ACPI_AML_OUT_USER );
@@ -582,7 +582,7 @@ static int acpi_aml_read_user(char __use/* sync head before removing logs */ smp_rmb (); p = &crc->buf[crc->tail]; - n =min (len,circ_count_to_end (crc)); + n =min_t (size_t, len,circ_count_to_end (crc));if (copy_to_user (buf, p, n)) { ret = -EFAULT ; goto out;
@@ -599,8 +599,8 @@ out:static ssize_t acpi_aml_read (struct file *file,char __user *buf,size_t count,loff_t *ppos) { -int ret =0 ; -int size =0 ; +ssize_t ret =0 ; +ssize_t size =0 ;if (!count)return 0 ;
@@ -639,11 +639,11 @@ again:return size >0 ? size : ret; } -static int acpi_aml_write_user (const char __user *buf,int len) +static ssize_t acpi_aml_write_user (const char __user *buf,size_t len) { -int ret;struct circ_buf *crc = &acpi_aml_io.in_crc; -int n; +ssize_t ret; +size_t n;char *p; ret =acpi_aml_lock_write (crc,ACPI_AML_IN_USER );
@@ -652,7 +652,7 @@ static int acpi_aml_write_user(const cha/* sync tail before inserting cmds */ smp_mb (); p = &crc->buf[crc->head]; - n =min (len,circ_space_to_end (crc)); + n =min_t (size_t, len,circ_space_to_end (crc));if (copy_from_user (p, buf, n)) { ret = -EFAULT ; goto out;
@@ -663,14 +663,14 @@ static int acpi_aml_write_user(const cha ret = n; out:acpi_aml_unlock_fifo (ACPI_AML_IN_USER , ret >=0 ); -return n; +return ret; }static ssize_t acpi_aml_write (struct file *file,const char __user *buf,size_t count,loff_t *ppos) { -int ret =0 ; -int size =0 ; +ssize_t ret =0 ; +ssize_t size =0 ;if (!count)return 0 ;
Greg Kroah-Hartman
maintainerPATCH 168/276 arm64: dts: qcom: msm8916: Add missing MDSS reset
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Stephan Gerhold <[email protected]>
commit 99b78773c2ae55dcc01025f94eae8ce9700ae985 upstream.
On most MSM8916 devices (aside from the DragonBoard 410c), the bootloader already initializes the display to show the boot splash screen. In this situation, MDSS is already configured and left running when starting Linux. To avoid side effects from the bootloader configuration, the MDSS reset can be specified in the device tree to start again with a clean hardware state.
The reset for MDSS is currently missing in msm8916.dtsi, which causes errors when the MDSS driver tries to re-initialize the registers:
dsi_err_worker: status=6
dsi_err_worker: status=6
dsi_err_worker: status=6
...
It turns out that we have always indirectly worked around this by building the MDSS driver as a module. Before v6.17, the power domain was temporarily turned off until the module was loaded, long enough to clear the register contents. In v6.17, power domains are not turned off during boot until sync_state() happens, so this is no longer working. Even before v6.17 this resulted in broken behavior, but notably only when the MDSS driver was built-in instead of a module.
--- arch/arm64/boot/dts/qcom/msm8916.dtsi | 2 ++ 1 file changed, 2 insertions(+)
arch/arm64/boot/dts/qcom/msm8916.dtsi +2 -0
@@ -957,6 +957,8 @@ interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>; + resets = <&gcc GCC_MDSS_BCR>; + interrupt-controller; #interrupt-cells = <1>;
Greg Kroah-Hartman
maintainerPATCH 169/276 ARM: OMAP2+: pm33xx-core: ix device node reference leaks in amx3_idle_init
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Miaoqian Lin <[email protected]>
commit 74139a64e8cedb6d971c78d5d17384efeced1725 upstream.
Add missing of_node_put() calls to release device node references obtained via of_parse_phandle().
--- arch/arm/mach-omap2/pm33xx-core.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
arch/arm/mach-omap2/pm33xx-core.c +5 -1
@@ -393,12 +393,15 @@ static int __init amx3_idle_init(structif (!state_node)break ; -if (!of_device_is_available (state_node)) +if (!of_device_is_available (state_node)) { +of_node_put (state_node);continue ; + }if (i ==CPUIDLE_STATE_MAX ) {pr_warn ("%s: cpuidle states reached max possible\n" , __func__); +of_node_put (state_node);break ; }
@@ -408,6 +411,7 @@ static int __init amx3_idle_init(struct states[state_count].wfi_flags |=WFI_FLAG_WAKE_M3 |WFI_FLAG_FLUSH_CACHE ; +of_node_put (state_node); state_count++; }
Greg Kroah-Hartman
maintainerPATCH 170/276 xen/events: Cleanup find_virq() return codes
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jason Andryuk <[email protected]>
commit 08df2d7dd4ab2db8a172d824cda7872d5eca460a upstream.
rc is overwritten by the evtchn_status hypercall in each iteration, so the return value will be whatever the last iteration is. This could incorrectly return success even if the event channel was not found. Change to an explicit -ENOENT for an un-found virq and return 0 on a successful match.
Message-ID: <[email protected]>
--- drivers/xen/events/events_base.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
drivers/xen/events/events_base.c +4 -3
@@ -1331,10 +1331,11 @@ static int find_virq(unsigned int virq, {struct evtchn_status status;evtchn_port_t port; -int rc = -ENOENT ;memset (&status,0 ,sizeof (status));for (port =0 ; port <xen_evtchn_max_channels (); port++) { +int rc; + status.dom =DOMID_SELF ; status.port = port; rc =HYPERVISOR_event_channel_op (EVTCHNOP_status, &status);
@@ -1344,10 +1345,10 @@ static int find_virq(unsigned int virq,continue ;if (status.u.virq == virq && status.vcpu ==xen_vcpu_nr (cpu)) { *evtchn = port; -break ; +return 0 ; } } -return rc; +return -ENOENT ; }/**
Greg Kroah-Hartman
maintainerPATCH 171/276 xen/manage: Fix suspend error path
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lukas Wunner <[email protected]>
commit f770c3d858687252f1270265ba152d5c622e793f upstream.
The device power management API has the following asymmetry:
* dpm_suspend_start() does not clean up on failure (it requires a call to dpm_resume_end())
* dpm_suspend_end() does clean up on failure
(it does not require a call to dpm_resume_start())
The asymmetry was introduced by commit d8f3de0d2412 ("Suspend-related patches for 2.6.27") in June 2008: It removed a call to device_resume() from device_suspend() (which was later renamed to dpm_suspend_start()).
When Xen began using the device power management API in May 2008 with commit 0e91398f2a5d ("xen: implement save/restore"), the asymmetry did not yet exist. But since it was introduced, a call to dpm_resume_end() is missing in the error path of dpm_suspend_start(). Fix it.
Message-ID: <22453676d1ddcebbe81641bb68ddf587fee7e21e.1756990799.git.lukas@wunner.de>
--- drivers/xen/manage.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/xen/manage.c +2 -1
@@ -116,7 +116,7 @@ static void do_suspend(void) err =dpm_suspend_start (PMSG_FREEZE );if (err) {pr_err ("%s: dpm_suspend_start %d\n" , __func__, err); - goto out_thaw; + goto out_resume_end; }printk (KERN_DEBUG "suspending xenstore...\n" );
@@ -156,6 +156,7 @@ out_resume:else xs_suspend_cancel (); +out_resume_end:dpm_resume_end (si.cancelled ?PMSG_THAW :PMSG_RESTORE ); out_thaw:
Greg Kroah-Hartman
maintainerPATCH 172/276 firmware: meson_sm: fix device leak at probe
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit 8ece3173f87df03935906d0c612c2aeda9db92ca upstream.
Make sure to drop the reference to the secure monitor device taken by of_find_device_by_node() when looking up its driver data on behalf of other drivers (e.g. during probe).
Note that holding a reference to the platform device does not prevent its driver data from going away so there is no point in keeping the reference after the helper returns.
--- drivers/firmware/meson/meson_sm.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
drivers/firmware/meson/meson_sm.c +6 -1
@@ -225,11 +225,16 @@ EXPORT_SYMBOL(meson_sm_call_write);struct meson_sm_firmware *meson_sm_get (struct device_node *sm_node) {struct platform_device *pdev =of_find_device_by_node (sm_node); +struct meson_sm_firmware *fw;if (!pdev)return NULL ; -return platform_get_drvdata (pdev); + fw =platform_get_drvdata (pdev); + +put_device (&pdev->dev); + +return fw; }EXPORT_SYMBOL_GPL (meson_sm_get);
Greg Kroah-Hartman
maintainerPATCH 173/276 media: i2c: mt9v111: fix incorrect type for ret
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Qianfeng Rong <[email protected]>
commit bacd713145443dce7764bb2967d30832a95e5ec8 upstream.
Change "ret" from unsigned int to int type in mt9v111_calc_frame_rate() to store negative error codes or zero returned by __mt9v111_hw_reset() and other functions.
Storing the negative error codes in unsigned type, doesn't cause an issue at runtime but it's ugly as pants.
No effect on runtime.
--- drivers/media/i2c/mt9v111.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/media/i2c/mt9v111.c +1 -1
@@ -534,8 +534,8 @@ static int mt9v111_calc_frame_rate(strucstatic int mt9v111_hw_config (struct mt9v111_dev *mt9v111) {struct i2c_client *c = mt9v111->client; -unsigned int ret;u16 outfmtctrl2; +int ret;/* Force device reset. */ ret =__mt9v111_hw_reset (mt9v111);
Greg Kroah-Hartman
maintainerPATCH 174/276 drm/nouveau: fix bad ret code in nouveau_bo_move_prep
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shuhao Fu <[email protected]>
commit e4bea919584ff292c9156cf7d641a2ab3cbe27b0 upstream.
In nouveau_bo_move_prep, if nouveau_mem_map fails, an error code should be returned. Currently, it returns zero even if vmm addr is not correctly mapped.
--- drivers/gpu/drm/nouveau/nouveau_bo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/nouveau/nouveau_bo.c +1 -1
@@ -791,7 +791,7 @@ done:nvif_vmm_put (vmm, &old_mem->vma[1 ]);nvif_vmm_put (vmm, &old_mem->vma[0 ]); } -return 0 ; +return ret; } static int
Greg Kroah-Hartman
maintainerPATCH 175/276 btrfs: avoid potential out-of-bounds in btrfs_encode_fh()
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Anderson Nascimento <[email protected]>
commit dff4f9ff5d7f289e4545cc936362e01ed3252742 upstream.
The function btrfs_encode_fh() does not properly account for the three cases it handles.
Before writing to the file handle (fh), the function only returns to the user BTRFS_FID_SIZE_NON_CONNECTABLE (5 dwords, 20 bytes) or BTRFS_FID_SIZE_CONNECTABLE (8 dwords, 32 bytes).
However, when a parent exists and the root ID of the parent and the inode are different, the function writes BTRFS_FID_SIZE_CONNECTABLE_ROOT (10 dwords, 40 bytes).
If *max_len is not large enough, this write goes out of bounds because BTRFS_FID_SIZE_CONNECTABLE_ROOT is greater than BTRFS_FID_SIZE_CONNECTABLE originally returned.
This results in an 8-byte out-of-bounds write atfid->parent_root_objectid = parent_root_id.
A previous attempt to fix this issue was made but was lost.
https://lore.kernel.org/all/[email protected]/
Although this issue does not seem to be easily triggerable, it is a potential memory corruption bug that should be fixed. This patch resolves the issue by ensuring the function returns the appropriate size for all three cases and validates that *max_len is large enough before writing any data.
--- fs/btrfs/export.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
fs/btrfs/export.c +7 -1
@@ -22,7 +22,11 @@ static int btrfs_encode_fh(struct inodeint type;if (parent && (len <BTRFS_FID_SIZE_CONNECTABLE )) { - *max_len =BTRFS_FID_SIZE_CONNECTABLE ; +if (btrfs_root_id (BTRFS_I (inode)->root) != +btrfs_root_id (BTRFS_I (parent)->root)) + *max_len =BTRFS_FID_SIZE_CONNECTABLE_ROOT ; +else + *max_len =BTRFS_FID_SIZE_CONNECTABLE ;return FILEID_INVALID ; }else if (len <BTRFS_FID_SIZE_NON_CONNECTABLE ) { *max_len =BTRFS_FID_SIZE_NON_CONNECTABLE ;
@@ -44,6 +48,8 @@ static int btrfs_encode_fh(struct inode parent_root_id =BTRFS_I (parent)->root->root_key.objectid;if (parent_root_id != fid->root_objectid) { +if (*max_len <BTRFS_FID_SIZE_CONNECTABLE_ROOT ) +return FILEID_INVALID ; fid->parent_root_objectid = parent_root_id; len =BTRFS_FID_SIZE_CONNECTABLE_ROOT ; type =FILEID_BTRFS_WITH_PARENT_ROOT ;
Greg Kroah-Hartman
maintainerPATCH 176/276 bus: mhi: host: Do not use uninitialized dev pointer in mhi_init_irq_setup()
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Adam Xue <[email protected]>
commit d0856a6dff57f95cc5d2d74e50880f01697d0cc4 upstream.
In mhi_init_irq_setup, the device pointer used for dev_err() was not initialized. Use the pointer from mhi_cntrl instead.
--- drivers/bus/mhi/host/init.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
drivers/bus/mhi/host/init.c +2 -3
@@ -161,7 +161,6 @@ void mhi_deinit_free_irq(struct mhi_contint mhi_init_irq_setup (struct mhi_controller *mhi_cntrl) {struct mhi_event *mhi_event = mhi_cntrl->mhi_event; -struct device *dev = &mhi_cntrl->mhi_dev->dev;unsigned long irq_flags =IRQF_SHARED |IRQF_NO_SUSPEND ;int i, ret;
@@ -182,7 +181,7 @@ int mhi_init_irq_setup(struct mhi_controcontinue ;if (mhi_event->irq >= mhi_cntrl->nr_irqs) { -dev_err (dev,"irq %d not available for event ring\n" , +dev_err (mhi_cntrl->cntrl_dev,"irq %d not available for event ring\n" , mhi_event->irq); ret = -EINVAL ; goto error_request;
@@ -193,7 +192,7 @@ int mhi_init_irq_setup(struct mhi_contro irq_flags, "mhi", mhi_event);if (ret) { -dev_err (dev,"Error requesting irq:%d for ev:%d\n" , +dev_err (mhi_cntrl->cntrl_dev,"Error requesting irq:%d for ev:%d\n" , mhi_cntrl->irq[mhi_event->irq], i); goto error_request; }
Greg Kroah-Hartman
maintainerPATCH 177/276 copy_sighand: Handle architectures where sizeof(unsigned long) < sizeof(u64)
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Simon Schuster <[email protected]>
commit 04ff48239f46e8b493571e260bd0e6c3a6400371 upstream.
With the introduction of clone3 in commit 7f192e3cd316 ("fork: add clone3") the effective bit width of clone_flags on all architectures was increased from 32-bit to 64-bit. However, the signature of the copy_* helper functions (e.g., copy_sighand) used by copy_process was not adapted.
As such, they truncate the flags on any 32-bit architectures that supports clone3 (arc, arm, csky, m68k, microblaze, mips32, openrisc, parisc32, powerpc32, riscv32, x86-32 and xtensa).
For copy_sighand with CLONE_CLEAR_SIGHAND being an actual u64 constant, this triggers an observable bug in kernel selftest clone3_clear_sighand:
if (clone_flags & CLONE_CLEAR_SIGHAND)
in function copy_sighand within fork.c will always fail given:
unsigned long /* == uint32_t */ clone_flags
#define CLONE_CLEAR_SIGHAND 0x100000000ULLThis commit fixes the bug by always passing clone_flags to copy_sighand via their declared u64 type, invariant of architecture-dependent integer sizes.
--- kernel/fork.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/fork.c +1 -1
@@ -1595,7 +1595,7 @@ static int copy_io(unsigned long clone_freturn 0 ; } -static int copy_sighand (unsigned long clone_flags,struct task_struct *tsk) +static int copy_sighand (u64 clone_flags,struct task_struct *tsk) {struct sighand_struct *sig;
Greg Kroah-Hartman
maintainerPATCH 178/276 cpufreq: intel_pstate: Fix object lifecycle issue in update_qos_request()
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rafael J. Wysocki <[email protected]>
commit 69e5d50fcf4093fb3f9f41c4f931f12c2ca8c467 upstream.
The cpufreq_cpu_put() call in update_qos_request() takes place too early because the latter subsequently calls freq_qos_update_request() that indirectly accesses the policy object in question through the QoS request object passed to it.
Fortunately, update_qos_request() is called under intel_pstate_driver_lock, so this issue does not matter for changing the intel_pstate operation mode, but it theoretically can cause a crash to occur on CPU device hot removal (which currently can only happen in virt, but it is formally supported nevertheless).
Address this issue by modifying update_qos_request() to drop the reference to the policy later.
--- drivers/cpufreq/intel_pstate.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
drivers/cpufreq/intel_pstate.c +5 -3
@@ -1307,10 +1307,10 @@ static void update_qos_request(enum freqcontinue ; req = policy->driver_data; -cpufreq_cpu_put (policy); - -if (!req) +if (!req) { +cpufreq_cpu_put (policy);continue ; + }if (hwp_active)intel_pstate_get_hwp_cap (cpu);
@@ -1326,6 +1326,8 @@ static void update_qos_request(enum freqif (freq_qos_update_request (req, freq) <0 )pr_warn ("Failed to update freq constraint: CPU%d\n" , i); + +cpufreq_cpu_put (policy); } }
Greg Kroah-Hartman
maintainerPATCH 179/276 crypto: atmel - Fix dma_unmap_sg() direction
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thomas Fourier <[email protected]>
commit f5d643156ef62216955c119216d2f3815bd51cb1 upstream.
It seems like everywhere in this file, dd->in_sg is mapped with DMA_TO_DEVICE and dd->out_sg is mapped with DMA_FROM_DEVICE.
--- drivers/crypto/atmel-tdes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/crypto/atmel-tdes.c +1 -1
@@ -548,7 +548,7 @@ static int atmel_tdes_crypt_start(structif (err && (dd->flags &TDES_FLAGS_FAST )) {dma_unmap_sg (dd->dev, dd->in_sg,1 ,DMA_TO_DEVICE ); -dma_unmap_sg (dd->dev, dd->out_sg,1 ,DMA_TO_DEVICE ); +dma_unmap_sg (dd->dev, dd->out_sg,1 ,DMA_FROM_DEVICE ); }return err;
Greg Kroah-Hartman
maintainerPATCH 180/276 fs/ntfs3: Fix a resource leak bug in wnd_extend()
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Haoxiang Li <[email protected]>
commit d68318471aa2e16222ebf492883e05a2d72b9b17 upstream.
Add put_bh() to decrease the refcount of 'bh' after the job is finished, preventing a resource leak.
--- fs/ntfs3/bitmap.c | 1 + 1 file changed, 1 insertion(+)
fs/ntfs3/bitmap.c +1 -0
@@ -1381,6 +1381,7 @@ int wnd_extend(struct wnd_bitmap *wnd, smark_buffer_dirty (bh);unlock_buffer (bh);/* err = sync_dirty_buffer(bh); */ +put_bh (bh); b0 =0 ; bits -= op;
Greg Kroah-Hartman
maintainerPATCH 181/276 iio: dac: ad5360: use int type to store negative error codes
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Qianfeng Rong <[email protected]>
commit f9381ece76de999a2065d5b4fdd87fa17883978c upstream.
Change the 'ret' variable in ad5360_update_ctrl() from unsigned int to int, as it needs to store either negative error codes or zero returned by ad5360_write_unlocked().
--- drivers/iio/dac/ad5360.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/iio/dac/ad5360.c +1 -1
@@ -262,7 +262,7 @@ static int ad5360_update_ctrl(struct iio unsigned int clr) {struct ad5360_state *st =iio_priv (indio_dev); -unsigned int ret; +int ret;mutex_lock (&st->lock);
Greg Kroah-Hartman
maintainerPATCH 182/276 iio: dac: ad5421: use int type to store negative error codes
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Qianfeng Rong <[email protected]>
commit 3379c900320954d768ed9903691fb2520926bbe3 upstream.
Change the 'ret' variable in ad5421_update_ctrl() from unsigned int to int, as it needs to store either negative error codes or zero returned by ad5421_write_unlocked().
--- drivers/iio/dac/ad5421.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/iio/dac/ad5421.c +1 -1
@@ -186,7 +186,7 @@ static int ad5421_update_ctrl(struct iio unsigned int clr) {struct ad5421_state *st =iio_priv (indio_dev); -unsigned int ret; +int ret;mutex_lock (&st->lock);
Greg Kroah-Hartman
maintainerPATCH 183/276 iio: frequency: adf4350: Fix prescaler usage.
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Hennerich <[email protected]>
commit 33d7ecbf69aa7dd4145e3b77962bcb8759eede3d upstream.
The ADF4350/1 features a programmable dual-modulus prescaler of 4/5 or 8/9. When set to 4/5, the maximum RF frequency allowed is 3 GHz. Therefore, when operating the ADF4351 above 3 GHz, this must be set to 8/9. In this context not the RF output frequency is meant
- it's the VCO frequency.
Therefore move the prescaler selection after we derived the VCO frequency from the desired RF output frequency.
This BUG may have caused PLL lock instabilities when operating the VCO at the very high range close to 4.4 GHz.
--- drivers/iio/frequency/adf4350.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-)
drivers/iio/frequency/adf4350.c +13 -7
@@ -143,6 +143,19 @@ static int adf4350_set_freq(struct adf43if (freq >ADF4350_MAX_OUT_FREQ || freq < st->min_out_freq)return -EINVAL ; + st->r4_rf_div_sel =0 ; + +/* +* !\TODO: The below computation is making sure we get a power of 2 +* shift (st->r4_rf_div_sel) so that freq becomes higher or equal to +* ADF4350_MIN_VCO_FREQ. This might be simplified with fls()/fls_long() +* and friends. +*/ +while (freq <ADF4350_MIN_VCO_FREQ ) { + freq <<=1 ; + st->r4_rf_div_sel++; + } +if (freq >ADF4350_MAX_FREQ_45_PRESC ) { prescaler =ADF4350_REG1_PRESCALER ; mdiv =75 ;
@@ -151,13 +164,6 @@ static int adf4350_set_freq(struct adf43 mdiv =23 ; } - st->r4_rf_div_sel =0 ; - -while (freq <ADF4350_MIN_VCO_FREQ ) { - freq <<=1 ; - st->r4_rf_div_sel++; - } -/* * Allow a predefined reference division factor * if not set, compute our own
Greg Kroah-Hartman
maintainerPATCH 184/276 init: handle bootloader identifier in kernel parameters
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Huacai Chen <[email protected]>
commit e416f0ed3c500c05c55fb62ee62662717b1c7f71 upstream.
BootLoaders (Grub, LILO, etc) may pass an identifier such as "BOOT_IMAGE= /boot/vmlinuz-x.y.z" to kernel parameters. But these identifiers are not recognized by the kernel itself so will be passed to userspace. However user space init program also don't recognize it.
KEXEC/KDUMP (kexec-tools) may also pass an identifier such as "kexec" on some architectures.
We cannot change BootLoader's behavior, because this behavior exists for many years, and there are already user space programs search BOOT_IMAGE= in /proc/cmdline to obtain the kernel image locations:
https://github.com/linuxdeepin/deepin-ab-recovery/blob/master/util.go
(search getBootOptions)
https://github.com/linuxdeepin/deepin-ab-recovery/blob/master/main.go
(search getKernelReleaseWithBootOption) So the the best way is handle (ignore) it by the kernel itself, which can avoid such boot warnings (if we use something like init=/bin/bash, bootloader identifier can even cause a crash):
Kernel command line: BOOT_IMAGE=(hd0,1)/vmlinuz-6.x root=/dev/sda3 ro console=tty Unknown kernel command line parameters "BOOT_IMAGE=(hd0,1)/vmlinuz-6.x", will be passed to user space.
--- init/main.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
init/main.c +14 -0
@@ -540,6 +540,14 @@ static int __init unknown_bootoption(cha const char *unused, void *arg) { size_t len = strlen(param); +int i; + +/* +* Well-known bootloader identifiers: +* 1. LILO/Grub pass "BOOT_IMAGE=..."; +* 2. kexec/kdump (kexec-tools) pass "kexec". +*/ +const char *bootloader[] = {"BOOT_IMAGE=" ,"kexec" ,NULL };/* Handle params aliased to sysctls */ if (sysctl_is_alias (param))
@@ -547,6 +555,12 @@ static int __init unknown_bootoption(charepair_env_string (param, val); +/* Handle bootloader identifier */ +for (i =0 ; bootloader[i]; i++) { +if (strstarts (param, bootloader[i])) +return 0 ; + } +/* Handle obsolete-style parameters */ if (obsolete_checksetup (param))return 0 ;
Greg Kroah-Hartman
maintainerPATCH 185/276 iio: imu: inv_icm42600: Drop redundant pm_runtime reinitialization in resume
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sean Nyekjaer <[email protected]>
commit a95a0b4e471a6d8860f40c6ac8f1cad9dde3189a upstream.
Remove unnecessary calls to pm_runtime_disable(), pm_runtime_set_active(), and pm_runtime_enable() from the resume path. These operations are not required here and can interfere with proper pm_runtime state handling, especially when resuming from a pm_runtime suspended state.
--- drivers/iio/imu/inv_icm42600/inv_icm42600_core.c | 4 ---- 1 file changed, 4 deletions(-)
drivers/iio/imu/inv_icm42600/inv_icm42600_core.c +0 -4
@@ -730,10 +730,6 @@ static int __maybe_unused inv_icm42600_rif (ret) goto out_unlock; -pm_runtime_disable (dev); -pm_runtime_set_active (dev); -pm_runtime_enable (dev); -/* restore sensors state */ ret = inv_icm42600_set_pwr_mgmt0(st, st->suspended.gyro, st->suspended.accel,
Greg Kroah-Hartman
maintainerPATCH 186/276 iommu/vt-d: PRS isnt usable if PDS isnt supported
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lu Baolu <[email protected]>
commit 5ef7e24c742038a5d8c626fdc0e3a21834358341 upstream.
The specification, Section 7.10, "Software Steps to Drain Page Requests & Responses," requires software to submit an Invalidation Wait Descriptor (inv_wait_dsc) with the Page-request Drain (PD=1) flag set, along with the Invalidation Wait Completion Status Write flag (SW=1). It then waits for the Invalidation Wait Descriptor's completion.
However, the PD field in the Invalidation Wait Descriptor is optional, as stated in Section 6.5.2.9, "Invalidation Wait Descriptor":
"Page-request Drain (PD): Remapping hardware implementations reporting
Page-request draining as not supported (PDS = 0 in ECAP_REG) treat this field as reserved."
This implies that if the IOMMU doesn't support the PDS capability, software can't drain page requests and group responses as expected.
Do not enable PCI/PRI if the IOMMU doesn't support PDS.
--- drivers/iommu/intel/iommu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/iommu/intel/iommu.c +1 -1
@@ -2659,7 +2659,7 @@ static struct dmar_domain *dmar_insert_o }if (info->ats_supported &&ecap_prs (iommu->ecap) && -pci_pri_supported (pdev)) +ecap_pds (iommu->ecap) &&pci_pri_supported (pdev)) info->pri_supported =1 ; } }
Greg Kroah-Hartman
maintainerPATCH 187/276 KEYS: trusted_tpm1: Compare HMAC values in constant time
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Biggers <[email protected]>
commit eed0e3d305530066b4fc5370107cff8ef1a0d229 upstream.
To prevent timing attacks, HMAC value comparison needs to be constant time. Replace the memcmp() with the correct function, crypto_memneq().
[For the Fixes commit I used the commit that introduced the memcmp(). It predates the introduction of crypto_memneq(), but it was still a bug at the time even though a helper function didn't exist yet.]
--- security/keys/trusted-keys/trusted_tpm1.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
security/keys/trusted-keys/trusted_tpm1.c +4 -3
@@ -7,6 +7,7 @@*/ #include <crypto/hash_info.h> +#include <crypto/algapi.h> #include <linux/init.h> #include <linux/slab.h> #include <linux/parser.h>
@@ -241,7 +242,7 @@ int TSS_checkhmac1(unsigned char *bufferif (ret <0 ) goto out; -if (memcmp (testhmac, authdata,SHA1_DIGEST_SIZE )) +if (crypto_memneq (testhmac, authdata,SHA1_DIGEST_SIZE )) ret = -EINVAL ; out:kfree_sensitive (sdesc);
@@ -334,7 +335,7 @@ static int TSS_checkhmac2(unsigned char TPM_NONCE_SIZE, ononce, 1, continueflag1, 0, 0);if (ret <0 ) goto out; -if (memcmp (testhmac1, authdata1,SHA1_DIGEST_SIZE )) { +if (crypto_memneq (testhmac1, authdata1,SHA1_DIGEST_SIZE )) { ret = -EINVAL ; goto out; }
@@ -343,7 +344,7 @@ static int TSS_checkhmac2(unsigned char TPM_NONCE_SIZE, ononce, 1, continueflag2, 0, 0);if (ret <0 ) goto out; -if (memcmp (testhmac2, authdata2,SHA1_DIGEST_SIZE )) +if (crypto_memneq (testhmac2, authdata2,SHA1_DIGEST_SIZE )) ret = -EINVAL ; out:kfree_sensitive (sdesc);
Greg Kroah-Hartman
maintainerPATCH 188/276 lib/genalloc: fix device leak in of_gen_pool_get()
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit 1260cbcffa608219fc9188a6cbe9c45a300ef8b5 upstream.
Make sure to drop the reference taken when looking up the genpool platform device in of_gen_pool_get() before returning the pool.
Note that holding a reference to a device does typically not prevent its devres managed resources from being released so there is no point in keeping the reference.
--- lib/genalloc.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
lib/genalloc.c +4 -1
@@ -899,8 +899,11 @@ struct gen_pool *of_gen_pool_get(structif (!name) name = np_pool->name; } -if (pdev) +if (pdev) { pool =gen_pool_get (&pdev->dev, name); +put_device (&pdev->dev); + } +of_node_put (np_pool);return pool;
Greg Kroah-Hartman
maintainerPATCH 189/276 openat2: dont trigger automounts with RESOLVE_NO_XDEV
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Askar Safin <[email protected]>
commit 042a60680de43175eb4df0977ff04a4eba9da082 upstream.
openat2 had a bug: if we pass RESOLVE_NO_XDEV, then openat2 doesn't traverse through automounts, but may still trigger them. (See the link for full bug report with reproducer.)
This commit fixes this bug.
--- fs/namei.c | 8 ++++++++ 1 file changed, 8 insertions(+)
fs/namei.c +8 -0
@@ -1307,6 +1307,10 @@ static int follow_automount(struct path dentry->d_inode)return -EISDIR ; +/* No need to trigger automounts if mountpoint crossing is disabled. */ +if (lookup_flags &LOOKUP_NO_XDEV ) +return -EXDEV ; +if (count && (*count)++ >=MAXSYMLINKS )return -ELOOP ;
@@ -1330,6 +1334,10 @@ static int __traverse_mounts(struct path/* Allow the filesystem to manage the transit without i_mutex * being held. */ if (flags &DCACHE_MANAGE_TRANSIT ) { +if (lookup_flags &LOOKUP_NO_XDEV ) { + ret = -EXDEV ; +break ; + } ret = path->dentry->d_op->d_manage (path, false); flags =smp_load_acquire (&path->dentry->d_flags);if (ret <0 )
Greg Kroah-Hartman
maintainerPATCH 190/276 parisc: dont reference obsolete termio struct for TC* constants
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sam James <[email protected]>
commit 8ec5a066f88f89bd52094ba18792b34c49dcd55a upstream.
Similar in nature to ab107276607af90b13a5994997e19b7b9731e251. glibc-2.42 drops the legacy termio struct, but the ioctls.h header still defines some TC* constants in terms of termio (via sizeof). Hardcode the values instead.
This fixes building Python for example, which falls over like:
./Modules/termios.c:1119:16: error: invalid application of 'sizeof' to incomplete type 'struct termio'
--- arch/parisc/include/uapi/asm/ioctls.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
arch/parisc/include/uapi/asm/ioctls.h +4 -4
@@ -10,10 +10,10 @@#define TCSETS _IOW('T', 17, struct termios)/* TCSETATTR */ #define TCSETSW _IOW('T', 18, struct termios)/* TCSETATTRD */ #define TCSETSF _IOW('T', 19, struct termios)/* TCSETATTRF */ -#define TCGETA _IOR('T', 1, struct termio) -#define TCSETA _IOW('T', 2, struct termio) -#define TCSETAW _IOW('T', 3, struct termio) -#define TCSETAF _IOW('T', 4, struct termio) +#define TCGETA 0x40125401 +#define TCSETA 0x80125402 +#define TCSETAW 0x80125403 +#define TCSETAF 0x80125404#define TCSBRK _IO('T', 5)#define TCXONC _IO('T', 6)#define TCFLSH _IO('T', 7)
Greg Kroah-Hartman
maintainerPATCH 191/276 nvme-pci: Add TUXEDO IBS Gen8 to Samsung sleep quirk
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Georg Gottleuber <[email protected]>
commit eeaed48980a7aeb0d3d8b438185d4b5a66154ff9 upstream.
On the TUXEDO InfinityBook S Gen8, a Samsung 990 Evo NVMe leads to a high power consumption in s2idle sleep (3.5 watts).
This patch applies 'Force No Simple Suspend' quirk to achieve a sleep with a lower power consumption, typically around 1 watts.
--- drivers/nvme/host/pci.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/nvme/host/pci.c +2 -0
@@ -2979,10 +2979,12 @@ static unsigned long check_vendor_combin* Exclude Samsung 990 Evo from NVME_QUIRK_SIMPLE_SUSPEND * because of high power consumption (> 2 Watt) in s2idle * sleep. Only some boards with Intel CPU are affected. +* (Note for testing: Samsung 990 Evo Plus has same PCI ID) */ if (dmi_match (DMI_BOARD_NAME ,"DN50Z-140HC-YD" ) ||dmi_match (DMI_BOARD_NAME ,"GMxPXxx" ) ||dmi_match (DMI_BOARD_NAME ,"GXxMRXx" ) || +dmi_match (DMI_BOARD_NAME ,"NS5X_NS7XAU" ) ||dmi_match (DMI_BOARD_NAME ,"PH4PG31" ) ||dmi_match (DMI_BOARD_NAME ,"PH4PRX1_PH6PRX1" ) ||dmi_match (DMI_BOARD_NAME ,"PH6PG01_PH6PG71" ))
Greg Kroah-Hartman
maintainerPATCH 192/276 powerpc/powernv/pci: Fix underflow and leak issue
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nam Cao <[email protected]>
commit a39087905af9ffecaa237a918a2c03a04e479934 upstream.
pnv_irq_domain_alloc() allocates interrupts at parent's interrupt domain. If it fails in the progress, all allocated interrupts are freed.
The number of successfully allocated interrupts so far is stored "i". However, "i - 1" interrupts are freed. This is broken:
- One interrupt is not be freed
- If "i" is zero, "i - 1" wraps around
Correct the number of freed interrupts to "i".
--- arch/powerpc/platforms/powernv/pci-ioda.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/powerpc/platforms/powernv/pci-ioda.c +1 -1
@@ -2243,7 +2243,7 @@ static int pnv_irq_domain_alloc(struct ireturn 0 ; out: -irq_domain_free_irqs_parent (domain, virq, i -1 ); +irq_domain_free_irqs_parent (domain, virq, i);msi_bitmap_free_hwirqs (&phb->msi_bmp, hwirq, nr_irqs);return ret; }
Greg Kroah-Hartman
maintainerPATCH 193/276 powerpc/pseries/msi: Fix potential underflow and leak issue
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nam Cao <[email protected]>
commit 3443ff3be6e59b80d74036bb39f5b6409eb23cc9 upstream.
pseries_irq_domain_alloc() allocates interrupts at parent's interrupt domain. If it fails in the progress, all allocated interrupts are freed.
The number of successfully allocated interrupts so far is stored "i". However, "i - 1" interrupts are freed. This is broken:
- One interrupt is not be freed
- If "i" is zero, "i - 1" wraps around
Correct the number of freed interrupts to 'i'.
--- arch/powerpc/platforms/pseries/msi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/powerpc/platforms/pseries/msi.c +1 -1
@@ -607,7 +607,7 @@ static int pseries_irq_domain_alloc(stru out:/* TODO: handle RTAS cleanup in ->msi_finish() ? */ -irq_domain_free_irqs_parent (domain, virq, i -1 ); +irq_domain_free_irqs_parent (domain, virq, i);return ret; }
Greg Kroah-Hartman
maintainerPATCH 194/276 pwm: berlin: Fix wrong register in suspend/resume
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jisheng Zhang <[email protected]>
commit 3a4b9d027e4061766f618292df91760ea64a1fcc upstream.
The 'enable' register should be BERLIN_PWM_EN rather than BERLIN_PWM_ENABLE, otherwise, the driver accesses wrong address, there will be cpu exception then kernel panic during suspend/resume.
--- drivers/pwm/pwm-berlin.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/pwm/pwm-berlin.c +2 -2
@@ -274,7 +274,7 @@ static int berlin_pwm_suspend(struct devif (!channel)continue ; - channel->enable =berlin_pwm_readl (bpc, i,BERLIN_PWM_ENABLE ); + channel->enable =berlin_pwm_readl (bpc, i,BERLIN_PWM_EN ); channel->ctrl =berlin_pwm_readl (bpc, i,BERLIN_PWM_CONTROL ); channel->duty =berlin_pwm_readl (bpc, i,BERLIN_PWM_DUTY ); channel->tcnt =berlin_pwm_readl (bpc, i,BERLIN_PWM_TCNT );
@@ -305,7 +305,7 @@ static int berlin_pwm_resume(struct deviberlin_pwm_writel (bpc, i, channel->ctrl,BERLIN_PWM_CONTROL );berlin_pwm_writel (bpc, i, channel->duty,BERLIN_PWM_DUTY );berlin_pwm_writel (bpc, i, channel->tcnt,BERLIN_PWM_TCNT ); -berlin_pwm_writel (bpc, i, channel->enable,BERLIN_PWM_ENABLE ); +berlin_pwm_writel (bpc, i, channel->enable,BERLIN_PWM_EN ); }return 0 ;
Greg Kroah-Hartman
maintainerPATCH 195/276 scsi: hpsa: Fix potential memory leak in hpsa_big_passthru_ioctl()
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thorsten Blum <[email protected]>
commit b81296591c567b12d3873b05a37b975707959b94 upstream.
Replace kmalloc() followed by copy_from_user() with memdup_user() to fix a memory leak that occurs when copy_from_user(buff[sg_used],,) fails and the 'cleanup1:' path does not free the memory for 'buff[sg_used]'. Using memdup_user() avoids this by freeing the memory internally.
Since memdup_user() already allocates memory, use kzalloc() in the else branch instead of manually zeroing 'buff[sg_used]' using memset(0).
--- drivers/scsi/hpsa.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-)
drivers/scsi/hpsa.c +12 -9
@@ -6528,18 +6528,21 @@ static int hpsa_big_passthru_ioctl(strucwhile (left) { sz = (left > ioc->malloc_size) ? ioc->malloc_size : left; buff_size[sg_used] = sz; - buff[sg_used] =kmalloc (sz,GFP_KERNEL ); -if (buff[sg_used] ==NULL ) { - status = -ENOMEM ; - goto cleanup1; - } +if (ioc->Request.Type.Direction &XFER_WRITE ) { -if (copy_from_user (buff[sg_used], data_ptr, sz)) { - status = -EFAULT ; + buff[sg_used] =memdup_user (data_ptr, sz); +if (IS_ERR (buff[sg_used])) { + status =PTR_ERR (buff[sg_used]); + goto cleanup1; + } + }else { + buff[sg_used] =kzalloc (sz,GFP_KERNEL ); +if (!buff[sg_used]) { + status = -ENOMEM ; goto cleanup1; } - }else -memset (buff[sg_used],0 , sz); + } + left -= sz; data_ptr += sz; sg_used++;
Greg Kroah-Hartman
maintainerPATCH 196/276 sctp: Fix MAC comparison to be constant-time
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Biggers <[email protected]>
commit dd91c79e4f58fbe2898dac84858033700e0e99fb upstream.
To prevent timing attacks, MACs need to be compared in constant time. Use the appropriate helper function for this.
--- net/sctp/sm_make_chunk.c | 3 ++- net/sctp/sm_statefuns.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-)
net/sctp/sm_make_chunk.c +2 -1
@@ -31,6 +31,7 @@#define pr_fmt (fmt) KBUILD_MODNAME ": " fmt#include <crypto/hash.h> +#include <crypto/algapi.h> #include <linux/types.h> #include <linux/kernel.h> #include <linux/ip.h>
@@ -1796,7 +1797,7 @@ struct sctp_association *sctp_unpack_coo } } -if (memcmp (digest, cookie->signature,SCTP_SIGNATURE_SIZE )) { +if (crypto_memneq (digest, cookie->signature,SCTP_SIGNATURE_SIZE )) { *error = -SCTP_IERROR_BAD_SIG ; goto fail; }
net/sctp/sm_statefuns.c +2 -1
@@ -30,6 +30,7 @@#define pr_fmt (fmt) KBUILD_MODNAME ": " fmt +#include <crypto/algapi.h> #include <linux/types.h> #include <linux/kernel.h> #include <linux/ip.h>
@@ -4402,7 +4403,7 @@ static enum sctp_ierror sctp_sf_authenti sh_key, GFP_ATOMIC);/* Discard the packet if the digests do not match */ -if (memcmp (save_digest, digest, sig_len)) { +if (crypto_memneq (save_digest, digest, sig_len)) {kfree (save_digest);return SCTP_IERROR_BAD_SIG ; }
Greg Kroah-Hartman
maintainerPATCH 197/276 sparc64: fix hugetlb for sun4u
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Anthony Yznaga <[email protected]>
commit 6fd44a481b3c6111e4801cec964627791d0f3ec5 upstream.
An attempt to exercise sparc hugetlb code in a sun4u-based guest running under qemu results in the guest hanging due to being stuck in a trap loop. This is due to invalid hugetlb TTEs being installed that do not have the expected _PAGE_PMD_HUGE and page size bits set. Although the breakage has gone apparently unnoticed for several years, fix it now so there is the option to exercise sparc hugetlb code under qemu. This can be useful because sun4v support in qemu does not support linux guests currently and sun4v-based hardware resources may not be readily available.
Fix tested with a 6.15.2 and 6.16-rc6 kernels by running libhugetlbfs tests on a qemu guest running Debian 13.
--- arch/sparc/mm/hugetlbpage.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+)
arch/sparc/mm/hugetlbpage.c +20 -0
@@ -133,6 +133,26 @@ hugetlb_get_unmapped_area(struct file *fstatic pte_t sun4u_hugepage_shift_to_tte (pte_t entry,unsigned int shift) { +unsigned long hugepage_size = _PAGE_SZ4MB_4U; + +pte_val (entry) =pte_val (entry) & ~_PAGE_SZALL_4U; + +switch (shift) { +case HPAGE_256MB_SHIFT : + hugepage_size = _PAGE_SZ256MB_4U; +pte_val (entry) |= _PAGE_PMD_HUGE; +break ; +case HPAGE_SHIFT : +pte_val (entry) |= _PAGE_PMD_HUGE; +break ; +case HPAGE_64K_SHIFT : + hugepage_size = _PAGE_SZ64K_4U; +break ; +default : +WARN_ONCE (1 ,"unsupported hugepage shift=%u\n" , shift); + } + +pte_val (entry) =pte_val (entry) | hugepage_size;return entry; }
Greg Kroah-Hartman
maintainerPATCH 198/276 sparc: fix error handling in scan_one_device()
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ma Ke <[email protected]>
commit 302c04110f0ce70d25add2496b521132548cd408 upstream.
Once of_device_register() failed, we should call put_device() to decrement reference count for cleanup. Or it could cause memory leak. So fix this by calling put_device(), then the name can be freed in kobject_cleanup().
Calling path: of_device_register() -> of_device_add() -> device_add(). As comment of device_add() says, 'if device_add() succeeds, you should call device_del() when you want to get rid of it. If device_add() has not succeeded, use only put_device() to drop the reference count'.
Found by code review.
--- arch/sparc/kernel/of_device_32.c | 1 + arch/sparc/kernel/of_device_64.c | 1 + 2 files changed, 2 insertions(+)
arch/sparc/kernel/of_device_32.c +1 -0
@@ -387,6 +387,7 @@ static struct platform_device * __init sif (of_device_register (op)) {printk ("%pOF: Could not register of device.\n" , dp); +put_device (&op->dev);kfree (op); op =NULL ; }
arch/sparc/kernel/of_device_64.c +1 -0
@@ -680,6 +680,7 @@ static struct platform_device * __init sif (of_device_register (op)) {printk ("%pOF: Could not register of device.\n" , dp); +put_device (&op->dev);kfree (op); op =NULL ; }
Greg Kroah-Hartman
maintainerPATCH 199/276 mtd: rawnand: fsmc: Default to autodetect buswidth
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Linus Walleij <[email protected]>
commit b8df622cf7f6808c85764e681847150ed6d85f3d upstream.
If you don't specify buswidth 2 (16 bits) in the device tree, FSMC doesn't even probe anymore:
fsmc-nand 10100000.flash: FSMC device partno 090,
manufacturer 80, revision 00, config 00
nand: device found, Manufacturer ID: 0x20, Chip ID: 0xb1
nand: ST Micro 10100000.flash
nand: bus width 8 instead of 16 bits
nand: No NAND device found
fsmc-nand 10100000.flash: probe with driver fsmc-nand failed
with error -22
With this patch to use autodetection unless buswidth is specified, the device is properly detected again:
fsmc-nand 10100000.flash: FSMC device partno 090,
manufacturer 80, revision 00, config 00
nand: device found, Manufacturer ID: 0x20, Chip ID: 0xb1
nand: ST Micro NAND 128MiB 1,8V 16-bit
nand: 128 MiB, SLC, erase size: 128 KiB, page size: 2048, OOB size: 64 fsmc-nand 10100000.flash: Using 1-bit HW ECC scheme Scanning device for bad blocks
I don't know where or how this happened, I think some change in the nand core.
--- drivers/mtd/nand/raw/fsmc_nand.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/mtd/nand/raw/fsmc_nand.c +5 -1
@@ -876,10 +876,14 @@ static int fsmc_nand_probe_config_dt(strif (!of_property_read_u32 (np,"bank-width" , &val)) {if (val ==2 ) { nand->options |=NAND_BUSWIDTH_16 ; - }else if (val !=1 ) { + }else if (val ==1 ) { + nand->options |=NAND_BUSWIDTH_AUTO ; + }else {dev_err (&pdev->dev,"invalid bank-width %u\n" , val);return -EINVAL ; } + }else { + nand->options |=NAND_BUSWIDTH_AUTO ; }if (of_get_property (np,"nand-skip-bbtscan" ,NULL ))
Greg Kroah-Hartman
maintainerPATCH 200/276 mmc: core: SPI mode remove cmd7
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rex Chen <[email protected]>
commit fec40f44afdabcbc4a7748e4278f30737b54bb1a upstream.
SPI mode doesn't support cmd7, so remove it in mmc_sdio_alive() and confirm if sdio is active by checking CCCR register value is available or not.
--- drivers/mmc/core/sdio.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/mmc/core/sdio.c +5 -1
@@ -929,7 +929,11 @@ static void mmc_sdio_remove(struct mmc_h*/ static int mmc_sdio_alive (struct mmc_host *host) { -return mmc_select_card (host->card); +if (!mmc_host_is_spi (host)) +return mmc_select_card (host->card); +else +return mmc_io_rw_direct (host->card,0 ,0 ,SDIO_CCCR_CCCR ,0 , +NULL ); }/*
Greg Kroah-Hartman
maintainerPATCH 201/276 memory: samsung: exynos-srom: Fix of_iomap leak in exynos_srom_probe
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhen Ni <[email protected]>
commit 6744085079e785dae5f7a2239456135407c58b25 upstream.
The of_platform_populate() call at the end of the function has a possible failure path, causing a resource leak.
Replace of_iomap() with devm_platform_ioremap_resource() to ensure automatic cleanup of srom->reg_base.
This issue was detected by smatch static analysis:drivers/memory/samsung/exynos-srom.c:155 exynos_srom_probe()warn:
'srom->reg_base' from of_iomap() not released on lines: 155.
--- drivers/memory/samsung/exynos-srom.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-)
drivers/memory/samsung/exynos-srom.c +4 -6
@@ -121,20 +121,18 @@ static int exynos_srom_probe(struct platreturn -ENOMEM ; srom->dev = dev; - srom->reg_base =of_iomap (np,0 ); -if (!srom->reg_base) { + srom->reg_base =devm_platform_ioremap_resource (pdev,0 ); +if (IS_ERR (srom->reg_base)) {dev_err (&pdev->dev,"iomap of exynos srom controller failed\n" ); -return -ENOMEM ; +return PTR_ERR (srom->reg_base); }platform_set_drvdata (pdev, srom); srom->reg_offset =exynos_srom_alloc_reg_dump (exynos_srom_offsets,ARRAY_SIZE (exynos_srom_offsets)); -if (!srom->reg_offset) { -iounmap (srom->reg_base); +if (!srom->reg_offset)return -ENOMEM ; - }for_each_child_of_node (np, child) {if (exynos_srom_configure_bank (srom, child)) {
Greg Kroah-Hartman
maintainerPATCH 202/276 rtc: interface: Ensure alarm irq is enabled when UIE is enabled
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Esben Haabendal <[email protected]>
commit 9db26d5855d0374d4652487bfb5aacf40821c469 upstream.
When setting a normal alarm, user-space is responsible for using RTC_AIE_ON/RTC_AIE_OFF to control if alarm irq should be enabled.
But when RTC_UIE_ON is used, interrupts must be enabled so that the requested irq events are generated.
When RTC_UIE_OFF is used, alarm irq is disabled if there are no other alarms queued, so this commit brings symmetry to that.
--- drivers/rtc/interface.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/rtc/interface.c +4 -0
@@ -583,6 +583,10 @@ int rtc_update_irq_enable(struct rtc_dev rtc->uie_rtctimer.node.expires =ktime_add (now, onesec); rtc->uie_rtctimer.period =ktime_set (1 ,0 ); err =rtc_timer_enqueue (rtc, &rtc->uie_rtctimer); +if (!err && rtc->ops && rtc->ops->alarm_irq_enable) + err = rtc->ops->alarm_irq_enable (rtc->dev.parent,1 ); +if (err) + goto out; }else {rtc_timer_remove (rtc, &rtc->uie_rtctimer); }
Greg Kroah-Hartman
maintainerPATCH 203/276 rtc: interface: Fix long-standing race when setting alarm
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Esben Haabendal <[email protected]>
commit 795cda8338eab036013314dbc0b04aae728880ab upstream.
As described in the old comment dating back to
commit 6610e0893b8b ("RTC: Rework RTC code to use timerqueue for events") from 2010, we have been living with a race window when setting alarm with an expiry in the near future (i.e. next second).
With 1 second resolution, it can happen that the second ticks after the check for the timer having expired, but before the alarm is actually set. When this happen, no alarm IRQ is generated, at least not with some RTC chips (isl12022 is an example of this).
With UIE RTC timer being implemented on top of alarm irq, being re-armed every second, UIE will occasionally fail to work, as an alarm irq lost due to this race will stop the re-arming loop.
For now, I have limited the additional expiry check to only be done for alarms set to next seconds. I expect it should be good enough, although I don't know if we can now for sure that systems with loads could end up causing the same problems for alarms set 2 seconds or even longer in the future.
I haven't been able to reproduce the problem with this check in place.
--- drivers/rtc/interface.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+)
drivers/rtc/interface.c +23 -0
@@ -442,6 +442,29 @@ static int __rtc_set_alarm(struct rtc_deelse err = rtc->ops->set_alarm (rtc->dev.parent, alarm); +/* +* Check for potential race described above. If the waiting for next +* second, and the second just ticked since the check above, either +* +* 1) It ticked after the alarm was set, and an alarm irq should be +* generated. +* +* 2) It ticked before the alarm was set, and alarm irq most likely will +* not be generated. +* +* While we cannot easily check for which of these two scenarios we +* are in, we can return -ETIME to signal that the timer has already +* expired, which is true in both cases. +*/ +if ((scheduled - now) <=1 ) { + err =__rtc_read_time (rtc, &tm); +if (err) +return err; + now =rtc_tm_to_time64 (&tm); +if (scheduled <= now) +return -ETIME ; + } +trace_rtc_set_alarm (rtc_tm_to_time64 (&alarm->time), err);return err; }
Greg Kroah-Hartman
maintainerPATCH 204/276 rseq/selftests: Use weak symbol reference, not definition, to link with glibc
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sean Christopherson <[email protected]>
commit a001cd248ab244633c5fabe4f7c707e13fc1d1cc upstream.
Add "extern" to the glibc-defined weak rseq symbols to convert the rseq selftest's usage from weak symbol definitions to weak symbol _references_. Effectively re-defining the glibc symbols wreaks havoc when building with -fno-common, e.g. generates segfaults when running multi-threaded programs, as dynamically linked applications end up with multiple versions of the symbols.
Building with -fcommon, which until recently has the been the default for GCC and clang, papers over the bug by allowing the linker to resolve the weak/tentative definition to glibc's "real" definition.
Note, the symbol itself (or rather its address), not the value of the symbol, is set to 0/NULL for unresolved weak symbol references, as the symbol doesn't exist and thus can't have a value. Check for a NULL rseq size pointer to handle the scenario where the test is statically linked against a libc that doesn't support rseq in any capacity.
--- tools/testing/selftests/rseq/rseq.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
tools/testing/selftests/rseq/rseq.c +4 -4
@@ -38,9 +38,9 @@* Define weak versions to play nice with binaries that are statically linked * against a libc that doesn't support registering its own rseq. */ -__weak ptrdiff_t __rseq_offset; -__weak unsigned int __rseq_size; -__weak unsigned int __rseq_flags; +extern __weak ptrdiff_t __rseq_offset; +extern __weak unsigned int __rseq_size; +extern __weak unsigned int __rseq_flags;static const ptrdiff_t *libc_rseq_offset_p = &__rseq_offset;static const unsigned int *libc_rseq_size_p = &__rseq_size;
@@ -124,7 +124,7 @@ void rseq_init(void)* libc not having registered a restartable sequence. Try to find the * symbols if that's the case. */ -if (!*libc_rseq_size_p) { +if (!libc_rseq_size_p || !*libc_rseq_size_p) { libc_rseq_offset_p =dlsym (RTLD_NEXT ,"__rseq_offset" ); libc_rseq_size_p =dlsym (RTLD_NEXT ,"__rseq_size" ); libc_rseq_flags_p =dlsym (RTLD_NEXT ,"__rseq_flags" );
Greg Kroah-Hartman
maintainerPATCH 205/276 PCI/sysfs: Ensure devices are powered for config reads
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Brian Norris <[email protected]>
commit 48991e4935078b05f80616c75d1ee2ea3ae18e58 upstream.
The "max_link_width", "current_link_speed", "current_link_width", "secondary_bus_number", and "subordinate_bus_number" sysfs files all access config registers, but they don't check the runtime PM state. If the device is in D3cold or a parent bridge is suspended, we may see -EINVAL, bogus values, or worse, depending on implementation details.
Wrap these access in pci_config_pm_runtime_{get,put}() like most of the rest of the similar sysfs attributes.
Notably, "max_link_speed" does not access config registers; it returns a cached value since d2bd39c0456b ("PCI: Store all PCIe Supported Link Speeds").
--- drivers/pci/pci-sysfs.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-)
drivers/pci/pci-sysfs.c +19 -1
@@ -174,8 +174,14 @@ static ssize_t max_link_width_show(struc struct device_attribute *attr, char *buf) { struct pci_dev *pdev = to_pci_dev(dev); +ssize_t ret; -return sysfs_emit (buf,"%u\n" ,pcie_get_width_cap (pdev)); +/* We read PCI_EXP_LNKCAP, so we need the device to be accessible. */ +pci_config_pm_runtime_get (pdev); + ret =sysfs_emit (buf,"%u\n" ,pcie_get_width_cap (pdev)); +pci_config_pm_runtime_put (pdev); + +return ret; }static DEVICE_ATTR_RO (max_link_width);
@@ -187,7 +193,10 @@ static ssize_t current_link_speed_show(sint err;enum pci_bus_speed speed; +pci_config_pm_runtime_get (pci_dev); err =pcie_capability_read_word (pci_dev,PCI_EXP_LNKSTA , &linkstat); +pci_config_pm_runtime_put (pci_dev); +if (err)return -EINVAL ;
@@ -204,7 +213,10 @@ static ssize_t current_link_width_show(su16 linkstat;int err; +pci_config_pm_runtime_get (pci_dev); err =pcie_capability_read_word (pci_dev,PCI_EXP_LNKSTA , &linkstat); +pci_config_pm_runtime_put (pci_dev); +if (err)return -EINVAL ;
@@ -220,7 +232,10 @@ static ssize_t secondary_bus_number_showu8 sec_bus;int err; +pci_config_pm_runtime_get (pci_dev); err =pci_read_config_byte (pci_dev,PCI_SECONDARY_BUS , &sec_bus); +pci_config_pm_runtime_put (pci_dev); +if (err)return -EINVAL ;
@@ -236,7 +251,10 @@ static ssize_t subordinate_bus_number_shu8 sub_bus;int err; +pci_config_pm_runtime_get (pci_dev); err =pci_read_config_byte (pci_dev,PCI_SUBORDINATE_BUS , &sub_bus); +pci_config_pm_runtime_put (pci_dev); +if (err)return -EINVAL ;
Greg Kroah-Hartman
maintainerPATCH 206/276 PCI/IOV: Add PCI rescan-remove locking when enabling/disabling SR-IOV
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Niklas Schnelle <[email protected]>
commit 05703271c3cdcc0f2a8cf6ebdc45892b8ca83520 upstream.
Before disabling SR-IOV via config space accesses to the parent PF, sriov_disable() first removes the PCI devices representing the VFs.
Since commit 9d16947b7583 ("PCI: Add global pci_lock_rescan_remove()") such removal operations are serialized against concurrent remove and rescan using the pci_rescan_remove_lock. No such locking was ever added in sriov_disable() however. In particular when commit 18f9e9d150fc ("PCI/IOV: Factor out sriov_add_vfs()") factored out the PCI device removal into sriov_del_vfs() there was still no locking around the pci_iov_remove_virtfn() calls.
On s390 the lack of serialization in sriov_disable() may cause double remove and list corruption with the below (amended) trace being observed:
PSW: 0704c00180000000 0000000c914e4b38 (klist_put+56)
GPRS: 000003800313fb48 0000000000000000 0000000100000001 0000000000000001
00000000f9b520a8 0000000000000000 0000000000002fbd 00000000f4cc9480 0000000000000001 0000000000000000 0000000000000000 0000000180692828 00000000818e8000 000003800313fe2c 000003800313fb20 000003800313fad8
#0 [3800313fb20] device_del at c9158ad5c
#1 [3800313fb88] pci_remove_bus_device at c915105ba #2 [3800313fbd0] pci_iov_remove_virtfn at c9152f198 #3 [3800313fc28] zpci_iov_remove_virtfn at c90fb67c0 #4 [3800313fc60] zpci_bus_remove_device at c90fb6104 #5 [3800313fca0] __zpci_event_availability at c90fb3dca #6 [3800313fd08] chsc_process_sei_nt0 at c918fe4a2 #7 [3800313fd60] crw_collect_info at c91905822 #8 [3800313fe10] kthread at c90feb390
#9 [3800313fe68] __ret_from_fork at c90f6aa64 #10 [3800313fe98] ret_from_fork at c9194f3f2.
This is because in addition to sriov_disable() removing the VFs, the platform also generates hot-unplug events for the VFs. This being the reverse operation to the hotplug events generated by sriov_enable() and handled via pdev->no_vf_scan. And while the event processing takes pci_rescan_remove_lock and checks whether the struct pci_dev still exists, the lack of synchronization makes this checking racy.
Other races may also be possible of course though given that this lack of locking persisted so long observable races seem very rare. Even on s390 the list corruption was only observed with certain devices since the platform events are only triggered by config accesses after the removal, so as long as the removal finished synchronously they would not race. Either way the locking is missing so fix this by adding it to the sriov_del_vfs() helper.
Just like PCI rescan-remove, locking is also missing in sriov_add_vfs() including for the error case where pci_stop_and_remove_bus_device() is called without the PCI rescan-remove lock being held. Even in the non-error case, adding new PCI devices and buses should be serialized via the PCI rescan-remove lock. Add the necessary locking.
--- drivers/pci/iov.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/pci/iov.c +5 -0
@@ -541,15 +541,18 @@ static int sriov_add_vfs(struct pci_devif (dev->no_vf_scan)return 0 ; +pci_lock_rescan_remove ();for (i =0 ; i < num_vfs; i++) { rc =pci_iov_add_virtfn (dev, i);if (rc) goto failed; } +pci_unlock_rescan_remove ();return 0 ; failed:while (i--)pci_iov_remove_virtfn (dev, i); +pci_unlock_rescan_remove ();return rc; }
@@ -669,8 +672,10 @@ static void sriov_del_vfs(struct pci_devstruct pci_sriov *iov = dev->sriov;int i; +pci_lock_rescan_remove ();for (i =0 ; i < iov->num_VFs; i++)pci_iov_remove_virtfn (dev, i); +pci_unlock_rescan_remove (); }static void sriov_disable (struct pci_dev *dev)
Greg Kroah-Hartman
maintainerPATCH 207/276 PCI/ERR: Fix uevent on failure to recover
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lukas Wunner <[email protected]>
commit 1cbc5e25fb70e942a7a735a1f3d6dd391afc9b29 upstream.
Upon failure to recover from a PCIe error through AER, DPC or EDR, a uevent is sent to inform user space about disconnection of the bridge whose subordinate devices failed to recover.
However the bridge itself is not disconnected. Instead, a uevent should be sent for each of the subordinate devices.
Only if the "bridge" happens to be a Root Complex Event Collector or Integrated Endpoint does it make sense to send a uevent for it (because there are no subordinate devices).
Right now if there is a mix of subordinate devices with and without pci_error_handlers, a BEGIN_RECOVERY event is sent for those with pci_error_handlers but no FAILED_RECOVERY event is ever sent for them afterwards. Fix it.
--- drivers/pci/pcie/err.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
drivers/pci/pcie/err.c +7 -1
@@ -102,6 +102,12 @@ static int report_normal_detected(structreturn report_error_detected (dev, pci_channel_io_normal, data); } +static int report_perm_failure_detected (struct pci_dev *dev,void *data) +{ +pci_uevent_ers (dev,PCI_ERS_RESULT_DISCONNECT ); +return 0 ; +} +static int report_mmio_enabled (struct pci_dev *dev,void *data) {pci_ers_result_t vote, *result = data;
@@ -263,7 +269,7 @@ pci_ers_result_t pcie_do_recovery(struct failed:pci_walk_bridge (bridge, pci_pm_runtime_put,NULL ); -pci_uevent_ers (bridge,PCI_ERS_RESULT_DISCONNECT ); +pci_walk_bridge (bridge, report_perm_failure_detected,NULL );/* TODO: Should kernel panic here? */ pci_info (bridge,"device recovery failed\n" );
Greg Kroah-Hartman
maintainerPATCH 208/276 PCI/AER: Fix missing uevent on recovery when a reset is requested
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Niklas Schnelle <[email protected]>
commit bbf7d0468d0da71d76cc6ec9bc8a224325d07b6b upstream.
Since commit 7b42d97e99d3 ("PCI/ERR: Always report current recovery status for udev") AER uses the result of error_detected() as parameter to pci_uevent_ers(). As pci_uevent_ers() however does not handle PCI_ERS_RESULT_NEED_RESET this results in a missing uevent for the beginning of recovery if drivers request a reset. Fix this by treating PCI_ERS_RESULT_NEED_RESET as beginning recovery.
--- drivers/pci/pci-driver.c | 1 + 1 file changed, 1 insertion(+)
drivers/pci/pci-driver.c +1 -0
@@ -1561,6 +1561,7 @@ void pci_uevent_ers(struct pci_dev *pdevswitch (err_type) {case PCI_ERS_RESULT_NONE :case PCI_ERS_RESULT_CAN_RECOVER : +case PCI_ERS_RESULT_NEED_RESET : envp[idx++] ="ERROR_EVENT=BEGIN_RECOVERY" ; envp[idx++] ="DEVICE_ONLINE=0" ;break ;
Greg Kroah-Hartman
maintainerPATCH 209/276 PCI/AER: Support errors introduced by PCIe r6.0
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lukas Wunner <[email protected]>
commit 6633875250b38b18b8638cf01e695de031c71f02 upstream.
PCIe r6.0 defined five additional errors in the Uncorrectable Error Status, Mask and Severity Registers (PCIe r7.0 sec 7.8.4.2ff).
lspci has been supporting them since commit 144b0911cc0b ("ls-ecaps:
extend decode support for more fields for AER CE and UE status"):
https://git.kernel.org/pub/scm/utils/pciutils/pciutils.git/commit/?id=144b0911cc0b
Amend the AER driver to recognize them as well, instead of logging them as "Unknown Error Bit".
--- drivers/pci/pcie/aer.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
drivers/pci/pcie/aer.c +6 -6
@@ -37,7 +37,7 @@#define AER_ERROR_SOURCES_MAX 128#define AER_MAX_TYPEOF_COR_ERRS 16/* as per PCI_ERR_COR_STATUS */ -#define AER_MAX_TYPEOF_UNCOR_ERRS 27/* as per PCI_ERR_UNCOR_STATUS*/ +#define AER_MAX_TYPEOF_UNCOR_ERRS 32/* as per PCI_ERR_UNCOR_STATUS*/ struct aer_err_source {unsigned int status;
@@ -513,11 +513,11 @@ static const char *aer_uncorrectable_err"AtomicOpBlocked" ,/* Bit Position 24 */ "TLPBlockedErr" ,/* Bit Position 25 */ "PoisonTLPBlocked" ,/* Bit Position 26 */ -NULL ,/* Bit Position 27 */ -NULL ,/* Bit Position 28 */ -NULL ,/* Bit Position 29 */ -NULL ,/* Bit Position 30 */ - NULL, /* Bit Position 31 */ +"DMWrReqBlocked" ,/* Bit Position 27 */ +"IDECheck" ,/* Bit Position 28 */ +"MisIDETLP" ,/* Bit Position 29 */ +"PCRC_CHECK" ,/* Bit Position 30 */ + "TLPXlatBlocked", /* Bit Position 31 */ }; static const char *aer_agent_string[] = {
Greg Kroah-Hartman
maintainerPATCH 210/276 PCI: keystone: Use devm_request_irq() to free "ks-pcie-error-irq" on exit
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Siddharth Vadapalli <[email protected]>
commit e51d05f523e43ce5d2bad957943a2b14f68078cd upstream.
Commit under Fixes introduced the IRQ handler for "ks-pcie-error-irq". The interrupt is acquired using "request_irq()" but is never freed if the driver exits due to an error. Although the section in the driver that invokes "request_irq()" has moved around over time, the issue hasn't been addressed until now.
Fix this by using "devm_request_irq()" which automatically frees the interrupt if the driver exits.
--- drivers/pci/controller/dwc/pci-keystone.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/pci/controller/dwc/pci-keystone.c +2 -2
@@ -1200,8 +1200,8 @@ static int ks_pcie_probe(struct platformif (irq <0 )return irq; - ret =request_irq (irq, ks_pcie_err_irq_handler,IRQF_SHARED , -"ks-pcie-error-irq" , ks_pcie); + ret =devm_request_irq (dev, irq, ks_pcie_err_irq_handler,IRQF_SHARED , +"ks-pcie-error-irq" , ks_pcie);if (ret <0 ) {dev_err (dev,"failed to request error IRQ %d\n" , irq);
Greg Kroah-Hartman
maintainerPATCH 211/276 PCI: tegra194: Fix broken tegra_pcie_ep_raise_msi_irq()
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Niklas Cassel <[email protected]>
commit b640d42a6ac9ba01abe65ec34f7c73aaf6758ab8 upstream.
The pci_epc_raise_irq() supplies a MSI or MSI-X interrupt number in range (1-N), as per the pci_epc_raise_irq() kdoc, where N is 32 for MSI.
But tegra_pcie_ep_raise_msi_irq() incorrectly uses the interrupt number as the MSI vector. This causes wrong MSI vector to be triggered, leading to the failure of PCI endpoint Kselftest MSI_TEST test case.
To fix this issue, convert the interrupt number to MSI vector.
--- drivers/pci/controller/dwc/pcie-tegra194.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/pci/controller/dwc/pcie-tegra194.c +2 -2
@@ -1839,10 +1839,10 @@ static int tegra_pcie_ep_raise_legacy_irstatic int tegra_pcie_ep_raise_msi_irq (struct tegra_pcie_dw *pcie,u16 irq) { -if (unlikely (irq >31 )) +if (unlikely (irq >32 ))return -EINVAL ; -appl_writel (pcie,BIT (irq),APPL_MSI_CTRL_1 ); +appl_writel (pcie,BIT (irq -1 ),APPL_MSI_CTRL_1 );return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 212/276 spi: cadence-quadspi: Flush posted register writes before INDAC access
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pratyush Yadav <[email protected]>
commit 29e0b471ccbd674d20d4bbddea1a51e7105212c5 upstream.
cqspi_indirect_read_execute() and cqspi_indirect_write_execute() first set the enable bit on APB region and then start reading/writing to the AHB region. On TI K3 SoCs these regions lie on different endpoints. This means that the order of the two operations is not guaranteed, and they might be reordered at the interconnect level.
It is possible for the AHB write to be executed before the APB write to enable the indirect controller, causing the transaction to be invalid and the write erroring out. Read back the APB region write before accessing the AHB region to make sure the write got flushed and the race condition is eliminated.
Message-ID: <[email protected]>
--- drivers/spi/spi-cadence-quadspi.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/spi/spi-cadence-quadspi.c +3 -0
@@ -694,6 +694,7 @@ static int cqspi_indirect_read_execute(sreinit_completion (&cqspi->transfer_complete);writel (CQSPI_REG_INDIRECTRD_START_MASK , reg_base +CQSPI_REG_INDIRECTRD ); +readl (reg_base +CQSPI_REG_INDIRECTRD );/* Flush posted write. */ while (remaining > 0) { if (!wait_for_completion_timeout(&cqspi->transfer_complete,
@@ -834,6 +835,8 @@ static int cqspi_indirect_write_execute(reinit_completion (&cqspi->transfer_complete);writel (CQSPI_REG_INDIRECTWR_START_MASK , reg_base +CQSPI_REG_INDIRECTWR ); +readl (reg_base +CQSPI_REG_INDIRECTWR );/* Flush posted write. */ +/* * As per 66AK2G02 TRM SPRUHY8F section 11.15.5.3 Indirect Access * Controller programming sequence, couple of cycles of
Greg Kroah-Hartman
maintainerPATCH 213/276 spi: cadence-quadspi: Flush posted register writes before DAC access
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pratyush Yadav <[email protected]>
commit 1ad55767e77a853c98752ed1e33b68049a243bd7 upstream.
cqspi_read_setup() and cqspi_write_setup() program the address width as the last step in the setup. This is likely to be immediately followed by a DAC region read/write. On TI K3 SoCs the DAC region is on a different endpoint from the register region. This means that the order of the two operations is not guaranteed, and they might be reordered at the interconnect level. It is possible that the DAC read/write goes through before the address width update goes through. In this situation if the previous command used a different address width the OSPI command is sent with the wrong number of address bytes, resulting in an invalid command and undefined behavior.
Read back the size register to make sure the write gets flushed before accessing the DAC region.
Message-ID: <[email protected]>
--- drivers/spi/spi-cadence-quadspi.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/spi/spi-cadence-quadspi.c +2 -0
@@ -666,6 +666,7 @@ static int cqspi_read_setup(struct cqspi reg &= ~CQSPI_REG_SIZE_ADDRESS_MASK ; reg |= (op->addr.nbytes -1 );writel (reg, reg_base +CQSPI_REG_SIZE ); +readl (reg_base +CQSPI_REG_SIZE );/* Flush posted write. */ return 0 ; }
@@ -810,6 +811,7 @@ static int cqspi_write_setup(struct cqsp reg &= ~CQSPI_REG_SIZE_ADDRESS_MASK ; reg |= (op->addr.nbytes -1 );writel (reg, reg_base +CQSPI_REG_SIZE ); +readl (reg_base +CQSPI_REG_SIZE );/* Flush posted write. */ return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 214/276 x86/umip: Check that the instruction opcode is at least two bytes
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sean Christopherson <[email protected]>
commit 32278c677947ae2f042c9535674a7fff9a245dd3 upstream.
When checking for a potential UMIP violation on #GP, verify the decoder found at least two opcode bytes to avoid false positives when the kernel encounters an unknown instruction that starts with 0f. Because the array of opcode.bytes is zero-initialized by insn_init(), peeking at bytes[1] will misinterpret garbage as a potential SLDT or STR instruction, and can incorrectly trigger emulation.
E.g. if a VPALIGNR instruction
62 83 c5 05 0f 08 ff vpalignr xmm17{k5},xmm23,XMMWORD PTR [r8],0xff
hits a #GP, the kernel emulates it as STR and squashes the #GP (and corrupts the userspace code stream).
Arguably the check should look for exactly two bytes, but no three byte opcodes use '0f 00 xx' or '0f 01 xx' as an escape, i.e. it should be impossible to get a false positive if the first two opcode bytes match '0f 00' or '0f 01'. Go with a more conservative check with respect to the existing code to minimize the chances of breaking userspace, e.g. due to decoder weirdness.
Analyzed by Nick Bray <[email protected]>.
--- arch/x86/kernel/umip.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/x86/kernel/umip.c +2 -2
@@ -156,8 +156,8 @@ static int identify_insn(struct insn *inif (!insn->modrm.nbytes)return -EINVAL ; -/* All the instructions of interest start with 0x0f. */ -if (insn->opcode.bytes[0 ] !=0xf ) +/* The instructions of interest have 2-byte opcodes: 0F 00 or 0F 01. */ +if (insn->opcode.nbytes <2 || insn->opcode.bytes[0 ] !=0xf )return -EINVAL ;if (insn->opcode.bytes[1 ] ==0x1 ) {
Greg Kroah-Hartman
maintainerPATCH 215/276 x86/umip: Fix decoding of register forms of 0F 01 (SGDT and SIDT aliases)
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sean Christopherson <[email protected]>
commit 27b1fd62012dfe9d3eb8ecde344d7aa673695ecf upstream.
Filter out the register forms of 0F 01 when determining whether or not to emulate in response to a potential UMIP violation #GP, as SGDT and SIDT only accept memory operands. The register variants of 0F 01 are used to encode instructions for things like VMX and SGX, i.e. not checking the Mod field would cause the kernel to incorrectly emulate on #GP, e.g. due to a CPL violation on VMLAUNCH.
--- arch/x86/kernel/umip.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
arch/x86/kernel/umip.c +11 -0
@@ -163,8 +163,19 @@ static int identify_insn(struct insn *inif (insn->opcode.bytes[1 ] ==0x1 ) {switch (X86_MODRM_REG (insn->modrm.value)) {case 0 : +/* The reg form of 0F 01 /0 encodes VMX instructions. */ +if (X86_MODRM_MOD (insn->modrm.value) ==3 ) +return -EINVAL ; +return UMIP_INST_SGDT ;case 1 : +/* +* The reg form of 0F 01 /1 encodes MONITOR/MWAIT, +* STAC/CLAC, and ENCLS. +*/ +if (X86_MODRM_MOD (insn->modrm.value) ==3 ) +return -EINVAL ; +return UMIP_INST_SIDT ;case 4 :return UMIP_INST_SMSW ;
Greg Kroah-Hartman
maintainerPATCH 216/276 mm/page_alloc: only set ALLOC_HIGHATOMIC for __GPF_HIGH allocations
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thadeu Lima de Souza Cascardo <[email protected]>
commit 6a204d4b14c99232e05d35305c27ebce1c009840 upstream.
Commit 524c48072e56 ("mm/page_alloc: rename ALLOC_HIGH to ALLOC_MIN_RESERVE") is the start of a series that explains how __GFP_HIGH, which implies ALLOC_MIN_RESERVE, is going to be used instead of __GFP_ATOMIC for high atomic reserves.
Commit eb2e2b425c69 ("mm/page_alloc: explicitly record high-order atomic allocations in alloc_flags") introduced ALLOC_HIGHATOMIC for such allocations of order higher than 0. It still used __GFP_ATOMIC, though.
Then, commit 1ebbb21811b7 ("mm/page_alloc: explicitly define how __GFP_HIGH non-blocking allocations accesses reserves") just turned that check for !__GFP_DIRECT_RECLAIM, ignoring that high atomic reserves were expected to test for __GFP_HIGH.
This leads to high atomic reserves being added for high-order GFP_NOWAIT allocations and others that clear __GFP_DIRECT_RECLAIM, which is unexpected. Later, those reserves lead to 0-order allocations going to the slow path and starting reclaim.
Quoted 1 line
From
/proc/pagetypeinfo, without the patch:
Node 0, zone DMA, type HighAtomic 0 0 0 0 0 0 0 0 0 0 0 Node 0, zone DMA32, type HighAtomic 1 8 10 9 7 3 0 0 0 0 0 Node 0, zone Normal, type HighAtomic 64 20 12 5 0 0 0 0 0 0 0
With the patch:
Node 0, zone DMA, type HighAtomic 0 0 0 0 0 0 0 0 0 0 0 Node 0, zone DMA32, type HighAtomic 0 0 0 0 0 0 0 0 0 0 0 Node 0, zone Normal, type HighAtomic 0 0 0 0 0 0 0 0 0 0 0
--- mm/page_alloc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
mm/page_alloc.c +1 -1
@@ -4743,7 +4743,7 @@ gfp_to_alloc_flags(gfp_t gfp_mask, unsigif (!(gfp_mask & __GFP_NOMEMALLOC)) { alloc_flags |=ALLOC_NON_BLOCK ; -if (order >0 ) +if (order >0 && (alloc_flags &ALLOC_MIN_RESERVE )) alloc_flags |=ALLOC_HIGHATOMIC ; }
Greg Kroah-Hartman
maintainerPATCH 217/276 NFSD: Fix destination buffer size in nfsd4_ssc_setup_dul()
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thorsten Blum <[email protected]>
commit ab1c282c010c4f327bd7addc3c0035fd8e3c1721 upstream.
Commit 5304877936c0 ("NFSD: Fix strncpy() fortify warning") replaced strncpy(,, sizeof(..)) with strlcpy(,, sizeof(..) - 1), but strlcpy() already guaranteed NUL-termination of the destination buffer and subtracting one byte potentially truncated the source string.
The incorrect size was then carried over in commit 72f78ae00a8e ("NFSD:
move from strlcpy with unused retval to strscpy") when switching from strlcpy() to strscpy().
Fix this off-by-one error by using the full size of the destination buffer again.
--- fs/nfsd/nfs4proc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/nfsd/nfs4proc.c +1 -1
@@ -1335,7 +1335,7 @@ try_again:return 0 ; }if (work) { -strscpy (work->nsui_ipaddr, ipaddr,sizeof (work->nsui_ipaddr) -1 ); +strscpy (work->nsui_ipaddr, ipaddr,sizeof (work->nsui_ipaddr));refcount_set (&work->nsui_refcnt,2 ); work->nsui_busy = true;list_add_tail (&work->nsui_list, &nn->nfsd_ssc_mount_list);
Greg Kroah-Hartman
maintainerPATCH 218/276 nfsd: nfserr_jukebox in nlm_fopen should lead to a retry
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Olga Kornievskaia <[email protected]>
commit a082e4b4d08a4a0e656d90c2c05da85f23e6d0c9 upstream.
When v3 NLM request finds a conflicting delegation, it triggers a delegation recall and nfsd_open fails with EAGAIN. nfsd_open then translates EAGAIN into nfserr_jukebox. In nlm_fopen, instead of returning nlm_failed for when there is a conflicting delegation, drop this NLM request so that the client retries. Once delegation is recalled and if a local lock is claimed, a retry would lead to nfsd returning a nlm_lck_blocked error or a successful nlm lock.
--- fs/nfsd/lockd.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+)
fs/nfsd/lockd.c +15 -0
@@ -48,6 +48,21 @@ nlm_fopen(struct svc_rqst *rqstp, structswitch (nfserr) {case nfs_ok:return 0 ; +case nfserr_jukebox: +/* this error can indicate a presence of a conflicting +* delegation to an NLM lock request. Options are: +* (1) For now, drop this request and make the client +* retry. When delegation is returned, client's lock retry +* will complete. +* (2) NLM4_DENIED as per "spec" signals to the client +* that the lock is unavailable now but client can retry. +* Linux client implementation does not. It treats +* NLM4_DENIED same as NLM4_FAILED and errors the request. +* (3) For the future, treat this as blocked lock and try +* to callback when the delegation is returned but might +* not have a proper lock request to block on. +*/ + fallthrough;case nfserr_dropit:return nlm_drop_reply;case nfserr_stale:
Greg Kroah-Hartman
maintainerPATCH 219/276 ext4: verify orphan file size is not too big
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jan Kara <[email protected]>
commit 0a6ce20c156442a4ce2a404747bb0fb05d54eeb3 upstream.
In principle orphan file can be arbitrarily large. However orphan replay needs to traverse it all and we also pin all its buffers in memory. Thus filesystems with absurdly large orphan files can lead to big amounts of memory consumed. Limit orphan file size to a sane value and also use kvmalloc() for allocating array of block descriptor structures to avoid large order allocations for sane but large orphan files.
Message-ID: <[email protected]>
--- fs/ext4/orphan.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-)
fs/ext4/orphan.c +12 -1
@@ -584,9 +584,20 @@ int ext4_init_orphan_info(struct super_bext4_msg (sb,KERN_ERR ,"get orphan inode failed" );return PTR_ERR (inode); } +/* +* This is just an artificial limit to prevent corrupted fs from +* consuming absurd amounts of memory when pinning blocks of orphan +* file in memory. +*/ +if (inode->i_size >8 <<20 ) { +ext4_msg (sb,KERN_ERR ,"orphan file too big: %llu" , + (unsigned long long )inode->i_size); + ret = -EFSCORRUPTED ; + goto out_put; + } oi->of_blocks = inode->i_size >> sb->s_blocksize_bits; oi->of_csum_seed =EXT4_I (inode)->i_csum_seed; - oi->of_binfo =kmalloc_array (oi->of_blocks, + oi->of_binfo =kvmalloc_array (oi->of_blocks,sizeof (struct ext4_orphan_block ),GFP_KERNEL );if (!oi->of_binfo) {
Greg Kroah-Hartman
maintainerPATCH 220/276 ext4: increase i_disksize to offset + len in ext4_update_disksize_before_punch()
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yongjian Sun <[email protected]>
commit 9d80eaa1a1d37539224982b76c9ceeee736510b9 upstream.
After running a stress test combined with fault injection, we performed fsck -a followed by fsck -fn on the filesystem image. During the second pass, fsck -fn reported:
Inode 131512, end of extent exceeds allowed value
(logical block 405, physical block 1180540, len 2)
This inode was not in the orphan list. Analysis revealed the following call chain that leads to the inconsistency:
ext4_da_write_end()
//does not update i_disksize
ext4_punch_hole()
//truncate folio, keep size
ext4_page_mkwrite()
ext4_block_page_mkwrite()
ext4_block_write_begin()
ext4_get_block()
//insert written extent without update i_disksizejournal commit
echo 1 > /sys/block/xxx/device/delete
da-write path updates i_size but does not update i_disksize. Then ext4_punch_hole truncates the da-folio yet still leaves i_disksize unchanged(in the ext4_update_disksize_before_punch function, the condition offset + len < size is met). Then ext4_page_mkwrite sees ext4_nonda_switch return 1 and takes the nodioread_nolock path, the folio about to be written has just been punched out, and it’s offset sits beyond the current i_disksize. This may result in a written extent being inserted, but again does not update i_disksize. If the journal gets committed and then the block device is yanked, we might run into this. It should be noted that replacing ext4_punch_hole with ext4_zero_range in the call sequence may also trigger this issue, as neither will update i_disksize under these circumstances.
To fix this, we can modify ext4_update_disksize_before_punch to increase i_disksize to min(i_size, offset + len) when both i_size and (offset + len) are greater than i_disksize.
Message-ID: <[email protected]>
--- fs/ext4/inode.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
fs/ext4/inode.c +8 -2
@@ -3906,7 +3906,11 @@ int ext4_can_truncate(struct inode *inod* We have to make sure i_disksize gets properly updated before we truncate * page cache due to hole punching or zero range. Otherwise i_disksize update * can get lost as it may have been postponed to submission of writeback but -* that will never happen after we truncate page cache. +* that will never happen if we remove the folio containing i_size from the +* page cache. Also if we punch hole within i_size but above i_disksize, +* following ext4_page_mkwrite() may mistakenly allocate written blocks over +* the hole and thus introduce allocated blocks beyond i_disksize which is +* not allowed (e2fsck would complain in case of crash). */ int ext4_update_disksize_before_punch (struct inode *inode,loff_t offset,loff_t len)
@@ -3917,9 +3921,11 @@ int ext4_update_disksize_before_punch(stloff_t size =i_size_read (inode);WARN_ON (!inode_is_locked (inode)); -if (offset > size || offset + len < size) +if (offset > size)return 0 ; +if (offset + len < size) + size = offset + len;if (EXT4_I (inode)->i_disksize >= size)return 0 ;
Greg Kroah-Hartman
maintainerPATCH 221/276 ext4: correctly handle queries for metadata mappings
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ojaswin Mujoo <[email protected]>
commit 46c22a8bb4cb03211da1100d7ee4a2005bf77c70 upstream.
Currently, our handling of metadata is _ambiguous_ in some scenarios, that is, we end up returning unknown if the range only covers the mapping partially.
For example, in the following case:
$ xfs_io -c fsmap -d
0: 254:16 [0..7]: static fs metadata 8
1: 254:16 [8..15]: special 102:1 8
2: 254:16 [16..5127]: special 102:2 5112
3: 254:16 [5128..5255]: special 102:3 128
4: 254:16 [5256..5383]: special 102:4 128
5: 254:16 [5384..70919]: inodes 65536
6: 254:16 [70920..70967]: unknown 48
...
$ xfs_io -c fsmap -d 24 33
0: 254:16 [24..39]: unknown 16 <--- incomplete reporting
$ xfs_io -c fsmap -d 24 33 (With patch)
0: 254:16 [16..5127]: special 102:2 5112
This is because earlier in ext4_getfsmap_meta_helper, we end up ignoring any extent that starts before our queried range, but overlaps it. While the man page [1] is a bit ambiguous on this, this fix makes the output make more sense since we are anyways returning an "unknown" extent. This is also consistent to how XFS does it:
$ xfs_io -c fsmap -d
...
6: 254:16 [104..127]: free space 24
7: 254:16 [128..191]: inodes 64
...
$ xfs_io -c fsmap -d 137 150
0: 254:16 [128..191]: inodes 64 <-- full extent returned
[1] https://man7.org/linux/man-pages/man2/ioctl_getfsmap.2.html
Message-ID: <023f37e35ee280cd9baac0296cbadcbe10995cab.1757058211.git.ojaswin@linux.ibm.com>
--- fs/ext4/fsmap.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-)
fs/ext4/fsmap.c +9 -5
@@ -74,7 +74,8 @@ static int ext4_getfsmap_dev_compare(constatic bool ext4_getfsmap_rec_before_low_key (struct ext4_getfsmap_info *info,struct ext4_fsmap *rec) { -return rec->fmr_physical < info->gfi_low.fmr_physical; +return rec->fmr_physical + rec->fmr_length <= + info->gfi_low.fmr_physical; }/*
@@ -200,15 +201,18 @@ static int ext4_getfsmap_meta_helper(str ext4_group_first_block_no(sb, agno)); fs_end = fs_start +EXT4_C2B (sbi, len); -/* Return relevant extents from the meta_list */ +/* +* Return relevant extents from the meta_list. We emit all extents that +* partially/fully overlap with the query range +*/ list_for_each_entry_safe (p, tmp, &info->gfi_meta_list, fmr_list) { -if (p->fmr_physical < info->gfi_next_fsblk) { +if (p->fmr_physical + p->fmr_length <= info->gfi_next_fsblk) {list_del (&p->fmr_list);kfree (p);continue ; } -if (p->fmr_physical <= fs_start || - p->fmr_physical + p->fmr_length <= fs_end) { +if (p->fmr_physical <= fs_end && + p->fmr_physical + p->fmr_length > fs_start) {/* Emit the retained free extent record if present */ if (info->gfi_lastfree.fmr_owner) { error = ext4_getfsmap_helper(sb, info,
Greg Kroah-Hartman
maintainerPATCH 222/276 ext4: guard against EA inode refcount underflow in xattr update
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ahmet Eray Karadag <[email protected]>
commit 57295e835408d8d425bef58da5253465db3d6888 upstream.
syzkaller found a path where ext4_xattr_inode_update_ref() reads an EA inode refcount that is already <= 0 and then applies ref_change (often -1). That lets the refcount underflow and we proceed with a bogus value, triggering errors like:
EXT4-fs error: EA inode <n> ref underflow: ref_count=-1 ref_change=-1 EXT4-fs warning: ea_inode dec ref err=-117
Make the invariant explicit: if the current refcount is non-positive, treat this as on-disk corruption, emit ext4_error_inode(), and fail the operation with -EFSCORRUPTED instead of updating the refcount. Delete the WARN_ONCE() as negative refcounts are now impossible; keep error reporting in ext4_error_inode().
This prevents the underflow and the follow-on orphan/cleanup churn.
Message-ID: <[email protected]>
--- fs/ext4/xattr.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-)
fs/ext4/xattr.c +8 -7
@@ -987,7 +987,7 @@ static int ext4_xattr_inode_update_ref(h int ref_change) {struct ext4_iloc iloc; -s64 ref_count; +u64 ref_count;int ret;inode_lock_nested (ea_inode,I_MUTEX_XATTR );
@@ -997,13 +997,17 @@ static int ext4_xattr_inode_update_ref(h goto out; ref_count =ext4_xattr_inode_get_ref (ea_inode); +if ((ref_count ==0 && ref_change <0 ) || (ref_count ==U64_MAX && ref_change >0 )) { +ext4_error_inode (ea_inode, __func__, __LINE__,0 , +"EA inode %lu ref wraparound: ref_count=%lld ref_change=%d" , + ea_inode->i_ino, ref_count, ref_change); + ret = -EFSCORRUPTED ; + goto out; + } ref_count += ref_change;ext4_xattr_inode_set_ref (ea_inode, ref_count);if (ref_change >0 ) { -WARN_ONCE (ref_count <=0 ,"EA inode %lu ref_count=%lld" , - ea_inode->i_ino, ref_count); -if (ref_count ==1 ) {WARN_ONCE (ea_inode->i_nlink,"EA inode %lu i_nlink=%u" , ea_inode->i_ino, ea_inode->i_nlink);
@@ -1012,9 +1016,6 @@ static int ext4_xattr_inode_update_ref(hext4_orphan_del (handle, ea_inode); } }else { -WARN_ONCE (ref_count <0 ,"EA inode %lu ref_count=%lld" , - ea_inode->i_ino, ref_count); -if (ref_count ==0 ) { WARN_ONCE(ea_inode->i_nlink != 1, "EA inode %lu i_nlink=%u",
Greg Kroah-Hartman
maintainerPATCH 223/276 ext4: free orphan info with kvfree
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jan Kara <[email protected]>
commit 971843c511c3c2f6eda96c6b03442913bfee6148 upstream.
Orphan info is now getting allocated with kvmalloc_array(). Free it with kvfree() instead of kfree() to avoid complaints from mm.
Message-ID: <[email protected]>
--- fs/ext4/orphan.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
fs/ext4/orphan.c +2 -2
@@ -513,7 +513,7 @@ void ext4_release_orphan_info(struct supreturn ;for (i =0 ; i < oi->of_blocks; i++)brelse (oi->of_binfo[i].ob_bh); -kfree (oi->of_binfo); +kvfree (oi->of_binfo); } static struct ext4_orphan_block_tail *ext4_orphan_block_tail(
@@ -638,7 +638,7 @@ int ext4_init_orphan_info(struct super_b out_free:for (i--; i >=0 ; i--)brelse (oi->of_binfo[i].ob_bh); -kfree (oi->of_binfo); +kvfree (oi->of_binfo); out_put:iput (inode);return ret;
Greg Kroah-Hartman
maintainerPATCH 224/276 lib/crypto/curve25519-hacl64: Disable KASAN with clang-17 and older
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nathan Chancellor <[email protected]>
commit 2f13daee2a72bb962f5fd356c3a263a6f16da965 upstream.
After commit 6f110a5e4f99 ("Disable SLUB_TINY for build testing"), which causes CONFIG_KASAN to be enabled in allmodconfig again, arm64 allmodconfig builds with clang-17 and older show an instance of -Wframe-larger-than (which breaks the build with CONFIG_WERROR=y):
lib/crypto/curve25519-hacl64.c:757:6: error: stack frame size (2336) exceeds limit (2048) in 'curve25519_generic' [-Werror,-Wframe-larger-than]
757 | void curve25519_generic(u8 mypublic[CURVE25519_KEY_SIZE],
| ^When KASAN is disabled, the stack usage is roughly quartered:
lib/crypto/curve25519-hacl64.c:757:6: error: stack frame size (608) exceeds limit (128) in 'curve25519_generic' [-Werror,-Wframe-larger-than]
757 | void curve25519_generic(u8 mypublic[CURVE25519_KEY_SIZE],
| ^Using '-Rpass-analysis=stack-frame-layout' shows the following variables and many, many 8-byte spills when KASAN is enabled:
Offset: [SP-144], Type: Variable, Align: 8, Size: 40
Offset: [SP-464], Type: Variable, Align: 8, Size: 320
Offset: [SP-784], Type: Variable, Align: 8, Size: 320
Offset: [SP-864], Type: Variable, Align: 32, Size: 80
Offset: [SP-896], Type: Variable, Align: 32, Size: 32
Offset: [SP-1016], Type: Variable, Align: 8, Size: 120
When KASAN is disabled, there are still spills but not at many and the variables list is smaller:
Offset: [SP-192], Type: Variable, Align: 32, Size: 80
Offset: [SP-224], Type: Variable, Align: 32, Size: 32
Offset: [SP-344], Type: Variable, Align: 8, Size: 120
Disable KASAN for this file when using clang-17 or older to avoid blowing out the stack, clearing up the warning.
--- lib/crypto/Makefile | 4 ++++ 1 file changed, 4 insertions(+)
lib/crypto/Makefile +4 -0
@@ -22,6 +22,10 @@ obj-$(CONFIG_CRYPTO_LIB_CURVE25519_GENER libcurve25519-generic-y := curve25519-fiat32.o libcurve25519-generic-$(CONFIG_ARCH_SUPPORTS_INT128) := curve25519-hacl64.o libcurve25519-generic-y += curve25519-generic.o +# clang versions prior to 18 may blow out the stack with KASAN +ifeq ($(call clang-min-version, 180000),) +KASAN_SANITIZE_curve25519-hacl64.o := n +endif obj-$(CONFIG_CRYPTO_LIB_CURVE25519) += libcurve25519.o libcurve25519-y += curve25519.o
Greg Kroah-Hartman
maintainerPATCH 225/276 KVM: x86: Dont (re)check L1 intercepts when completing userspace I/O
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sean Christopherson <[email protected]>
[ Upstream commit e750f85391286a4c8100275516973324b621a269 ]
When completing emulation of instruction that generated a userspace exit for I/O, don't recheck L1 intercepts as KVM has already finished that phase of instruction execution, i.e. has already committed to allowing L2 to perform I/O. If L1 (or host userspace) modifies the I/O permission bitmaps during the exit to userspace, KVM will treat the access as being intercepted despite already having emulated the I/O access.
Pivot on EMULTYPE_NO_DECODE to detect that KVM is completing emulation. Of the three users of EMULTYPE_NO_DECODE, only complete_emulated_io() (the intended "recipient") can reach the code in question. gp_interception()'s use is mutually exclusive with is_guest_mode(), and complete_emulated_insn_gp() unconditionally pairs EMULTYPE_NO_DECODE with EMULTYPE_SKIP.
The bad behavior was detected by a syzkaller program that toggles port I/O interception during the userspace I/O exit, ultimately resulting in a WARN on vcpu->arch.pio.count being non-zero due to KVM no completing emulation of the I/O instruction.
WARNING: CPU: 23 PID: 1083 at arch/x86/kvm/x86.c:8039 emulator_pio_in_out+0x154/0x170 [kvm] Modules linked in: kvm_intel kvm irqbypass CPU: 23 UID: 1000 PID: 1083 Comm: repro Not tainted 6.16.0-rc5-c1610d2d66b1-next-vm #74 NONE Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 0.0.0 02/06/2015 RIP: 0010:emulator_pio_in_out+0x154/0x170 [kvm] PKRU: 55555554 Call Trace: <TASK> kvm_fast_pio+0xd6/0x1d0 [kvm] vmx_handle_exit+0x149/0x610 [kvm_intel] kvm_arch_vcpu_ioctl_run+0xda8/0x1ac0 [kvm] kvm_vcpu_ioctl+0x244/0x8c0 [kvm] __x64_sys_ioctl+0x8a/0xd0 do_syscall_64+0x5d/0xc60 entry_SYSCALL_64_after_hwframe+0x4b/0x53 </TASK>
--- arch/x86/kvm/emulate.c | 11 ++++------- arch/x86/kvm/kvm_emulate.h | 2 +- arch/x86/kvm/x86.c | 9 ++++++++- 3 files changed, 13 insertions(+), 9 deletions(-)
arch/x86/kvm/emulate.c +4 -7
@@ -5452,12 +5452,11 @@ void init_decode_cache(struct x86_emulat ctxt->mem_read.end =0 ; } -int x86_emulate_insn (struct x86_emulate_ctxt *ctxt) +int x86_emulate_insn (struct x86_emulate_ctxt *ctxt,bool check_intercepts) {const struct x86_emulate_ops *ops = ctxt->ops;int rc =X86EMUL_CONTINUE ;int saved_dst_type = ctxt->dst.type; -unsigned emul_flags; ctxt->mem_read.pos =0 ;
@@ -5471,8 +5470,6 @@ int x86_emulate_insn(struct x86_emulate_ rc =emulate_ud (ctxt); goto done; } - - emul_flags = ctxt->ops->get_hflags (ctxt);if (unlikely (ctxt->d & (No64|Undefined|Sse|Mmx|Intercept|CheckPerm|Priv|Prot|String))) { if ((ctxt->mode == X86EMUL_MODE_PROT64 && (ctxt->d & No64)) ||
@@ -5506,7 +5503,7 @@ int x86_emulate_insn(struct x86_emulate_fetch_possible_mmx_operand (&ctxt->dst); } -if (unlikely (emul_flags &X86EMUL_GUEST_MASK ) && ctxt->intercept) { +if (unlikely (check_intercepts) && ctxt->intercept) { rc =emulator_check_intercept (ctxt, ctxt->intercept,X86_ICPT_PRE_EXCEPT );if (rc !=X86EMUL_CONTINUE )
@@ -5535,7 +5532,7 @@ int x86_emulate_insn(struct x86_emulate_ goto done; } -if (unlikely (emul_flags &X86EMUL_GUEST_MASK ) && (ctxt->d & Intercept)) { +if (unlikely (check_intercepts) && (ctxt->d & Intercept)) { rc =emulator_check_intercept (ctxt, ctxt->intercept,X86_ICPT_POST_EXCEPT );if (rc !=X86EMUL_CONTINUE )
@@ -5589,7 +5586,7 @@ int x86_emulate_insn(struct x86_emulate_ special_insn: -if (unlikely (emul_flags &X86EMUL_GUEST_MASK ) && (ctxt->d & Intercept)) { +if (unlikely (check_intercepts) && (ctxt->d & Intercept)) { rc =emulator_check_intercept (ctxt, ctxt->intercept,X86_ICPT_POST_MEMACCESS );if (rc !=X86EMUL_CONTINUE )
arch/x86/kvm/kvm_emulate.h +1 -1
@@ -496,7 +496,7 @@ bool x86_page_table_writing_insn(struct#define EMULATION_RESTART 1#define EMULATION_INTERCEPTED 2void init_decode_cache (struct x86_emulate_ctxt *ctxt); -int x86_emulate_insn (struct x86_emulate_ctxt *ctxt); +int x86_emulate_insn (struct x86_emulate_ctxt *ctxt,bool check_intercepts);int emulator_task_switch (struct x86_emulate_ctxt *ctxt,u16 tss_selector,int idt_index,int reason,bool has_error_code,u32 error_code);
arch/x86/kvm/x86.c +8 -1
@@ -8209,7 +8209,14 @@ restart: ctxt->exception.address =0 ; } - r =x86_emulate_insn (ctxt); +/* +* Check L1's instruction intercepts when emulating instructions for +* L2, unless KVM is re-emulating a previously decoded instruction, +* e.g. to complete userspace I/O, in which case KVM has already +* checked the intercepts. +*/ + r =x86_emulate_insn (ctxt,is_guest_mode (vcpu) && + !(emulation_type &EMULTYPE_NO_DECODE ));if (r ==EMULATION_INTERCEPTED )return 1 ;
Greg Kroah-Hartman
maintainerPATCH 226/276 ASoC: codecs: wcd934x: Simplify with dev_err_probe
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Krzysztof Kozlowski <[email protected]>
[ Upstream commit fa92f4294283cc7d1f29151420be9e9336182518 ]
Replace dev_err() in probe() path with dev_err_probe() to:
1. Make code a bit simpler and easier to read,
2. Do not print messages on deferred probe.
Stable-dep-of: 4e65bda8273c ("ASoC: wcd934x: fix error handling in wcd934x_codec_parse_data()")
--- sound/soc/codecs/wcd934x.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-)
sound/soc/codecs/wcd934x.c +7 -12
@@ -5885,10 +5885,9 @@ static int wcd934x_codec_parse_data(struslim_get_logical_addr (wcd->sidev); wcd->if_regmap =regmap_init_slimbus (wcd->sidev, &wcd934x_ifc_regmap_config); -if (IS_ERR (wcd->if_regmap)) { -dev_err (dev,"Failed to allocate ifc register map\n" ); -return PTR_ERR (wcd->if_regmap); - } +if (IS_ERR (wcd->if_regmap)) +return dev_err_probe (dev,PTR_ERR (wcd->if_regmap), +"Failed to allocate ifc register map\n" );of_property_read_u32 (dev->parent->of_node,"qcom,dmic-sample-rate" , &wcd->dmic_sample_rate);
@@ -5940,19 +5939,15 @@ static int wcd934x_codec_probe(struct plmemcpy (wcd->tx_chs, wcd934x_tx_chs,sizeof (wcd934x_tx_chs)); irq =regmap_irq_get_virq (data->irq_data,WCD934X_IRQ_SLIMBUS ); -if (irq <0 ) { -dev_err (wcd->dev,"Failed to get SLIM IRQ\n" ); -return irq; - } +if (irq <0 ) +return dev_err_probe (wcd->dev, irq,"Failed to get SLIM IRQ\n" ); ret =devm_request_threaded_irq (dev, irq,NULL , wcd934x_slim_irq_handler,IRQF_TRIGGER_RISING |IRQF_ONESHOT ,"slim" , wcd); -if (ret) { -dev_err (dev,"Failed to request slimbus irq\n" ); -return ret; - } +if (ret) +return dev_err_probe (dev, ret,"Failed to request slimbus irq\n" );wcd934x_register_mclk_output (wcd);platform_set_drvdata (pdev, wcd);
Greg Kroah-Hartman
maintainerPATCH 227/276 ASoC: wcd934x: fix error handling in wcd934x_codec_parse_data()
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ma Ke <[email protected]>
[ Upstream commit 4e65bda8273c938039403144730923e77916a3d7 ]
wcd934x_codec_parse_data() contains a device reference count leak in of_slim_get_device() where device_find_child() increases the reference count of the device but this reference is not properly decreased in the success path. Add put_device() in wcd934x_codec_parse_data() and add devm_add_action_or_reset() in the probe function, which ensures that the reference count of the device is correctly managed.
Memory leak in regmap_init_slimbus() as the allocated regmap is not released when the device is removed. Using devm_regmap_init_slimbus() instead of regmap_init_slimbus() to ensure automatic regmap cleanup on device removal.
Calling path: of_slim_get_device() -> of_find_slim_device() -> device_find_child(). As comment of device_find_child() says, 'NOTE:
you will need to drop the reference with put_device() after use.'.
Found by code review.
--- sound/soc/codecs/wcd934x.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-)
sound/soc/codecs/wcd934x.c +15 -2
@@ -5863,6 +5863,13 @@ static const struct snd_soc_component_dr .set_jack = wcd934x_codec_set_jack, }; +static void wcd934x_put_device_action (void *data) +{ +struct device *dev = data; + +put_device (dev); +} +static int wcd934x_codec_parse_data (struct wcd934x_codec *wcd) {struct device *dev = &wcd->sdev->dev;
@@ -5883,11 +5890,13 @@ static int wcd934x_codec_parse_data(stru }slim_get_logical_addr (wcd->sidev); - wcd->if_regmap =regmap_init_slimbus (wcd->sidev, + wcd->if_regmap =devm_regmap_init_slimbus (wcd->sidev, &wcd934x_ifc_regmap_config); -if (IS_ERR (wcd->if_regmap)) +if (IS_ERR (wcd->if_regmap)) { +put_device (&wcd->sidev->dev);return dev_err_probe (dev,PTR_ERR (wcd->if_regmap),"Failed to allocate ifc register map\n" ); + }of_property_read_u32 (dev->parent->of_node,"qcom,dmic-sample-rate" , &wcd->dmic_sample_rate);
@@ -5931,6 +5940,10 @@ static int wcd934x_codec_probe(struct plreturn ret; } + ret =devm_add_action_or_reset (dev, wcd934x_put_device_action, &wcd->sidev->dev); +if (ret) +return ret; +/* set default rate 9P6MHz */ regmap_update_bits(wcd->regmap, WCD934X_CODEC_RPM_CLK_MCLK_CFG, WCD934X_CODEC_RPM_CLK_MCLK_CFG_MCLK_MASK,
Greg Kroah-Hartman
maintainerPATCH 228/276 Squashfs: add additional inode sanity checking
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Phillip Lougher <[email protected]>
[ Upstream commit 9ee94bfbe930a1b39df53fa2d7b31141b780eb5a ]
Patch series "Squashfs: performance improvement and a sanity check".
This patchset adds an additional sanity check when reading regular file inodes, and adds support for SEEK_DATA/SEEK_HOLE lseek() whence values.
This patch (of 2):
Add an additional sanity check when reading regular file inodes.
A regular file if the file size is an exact multiple of the filesystem block size cannot have a fragment. This is because by definition a fragment block stores tailends which are not a whole block in size.
Stable-dep-of: 9f1c14c1de1b ("Squashfs: reject negative file sizes in squashfs_read_inode()")
--- fs/squashfs/inode.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-)
fs/squashfs/inode.c +18 -2
@@ -140,8 +140,17 @@ int squashfs_read_inode(struct inode *inif (err <0 ) goto failed_read; + inode->i_size =le32_to_cpu (sqsh_ino->file_size); frag =le32_to_cpu (sqsh_ino->fragment);if (frag !=SQUASHFS_INVALID_FRAG ) { +/* +* the file cannot have a fragment (tailend) and have a +* file size a multiple of the block size +*/ +if ((inode->i_size & (msblk->block_size -1 )) ==0 ) { + err = -EINVAL ; + goto failed_read; + } frag_offset =le32_to_cpu (sqsh_ino->offset); frag_size =squashfs_frag_lookup (sb, frag, &frag_blk);if (frag_size <0 ) {
@@ -155,7 +164,6 @@ int squashfs_read_inode(struct inode *in }set_nlink (inode,1 ); - inode->i_size =le32_to_cpu (sqsh_ino->file_size); inode->i_fop = &generic_ro_fops; inode->i_mode |=S_IFREG ; inode->i_blocks = ((inode->i_size -1 ) >>9 ) +1 ;
@@ -184,8 +192,17 @@ int squashfs_read_inode(struct inode *inif (err <0 ) goto failed_read; + inode->i_size =le64_to_cpu (sqsh_ino->file_size); frag =le32_to_cpu (sqsh_ino->fragment);if (frag !=SQUASHFS_INVALID_FRAG ) { +/* +* the file cannot have a fragment (tailend) and have a +* file size a multiple of the block size +*/ +if ((inode->i_size & (msblk->block_size -1 )) ==0 ) { + err = -EINVAL ; + goto failed_read; + } frag_offset =le32_to_cpu (sqsh_ino->offset); frag_size =squashfs_frag_lookup (sb, frag, &frag_blk);if (frag_size <0 ) {
@@ -200,7 +217,6 @@ int squashfs_read_inode(struct inode *in xattr_id =le32_to_cpu (sqsh_ino->xattr);set_nlink (inode,le32_to_cpu (sqsh_ino->nlink)); - inode->i_size =le64_to_cpu (sqsh_ino->file_size); inode->i_op = &squashfs_inode_ops; inode->i_fop = &generic_ro_fops; inode->i_mode |=S_IFREG ;
Greg Kroah-Hartman
maintainerPATCH 229/276 Squashfs: reject negative file sizes in squashfs_read_inode()
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Phillip Lougher <[email protected]>
[ Upstream commit 9f1c14c1de1bdde395f6cc893efa4f80a2ae3b2b ]
Syskaller reports a "WARNING in ovl_copy_up_file" in overlayfs.
This warning is ultimately caused because the underlying Squashfs file system returns a file with a negative file size.
This commit checks for a negative file size and returns EINVAL.
--- fs/squashfs/inode.c | 4 ++++ 1 file changed, 4 insertions(+)
fs/squashfs/inode.c +4 -0
@@ -193,6 +193,10 @@ int squashfs_read_inode(struct inode *in goto failed_read; inode->i_size =le64_to_cpu (sqsh_ino->file_size); +if (inode->i_size <0 ) { + err = -EINVAL ; + goto failed_read; + } frag =le32_to_cpu (sqsh_ino->fragment);if (frag !=SQUASHFS_INVALID_FRAG ) {/*
Greg Kroah-Hartman
maintainerPATCH 230/276 media: mc: Clear minor number before put device
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Edward Adam Davis <[email protected]>
[ Upstream commit 8cfc8cec1b4da88a47c243a11f384baefd092a50 ]
The device minor should not be cleared after the device is released.
--- drivers/media/mc/mc-devnode.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-)
drivers/media/mc/mc-devnode.c +1 -5
@@ -50,11 +50,6 @@ static void media_devnode_release(struct {struct media_devnode *devnode =to_media_devnode (cd); -mutex_lock (&media_devnode_lock); -/* Mark device node number as free */ -clear_bit (devnode->minor, media_devnode_nums); -mutex_unlock (&media_devnode_lock); -/* Release media_devnode and perform other cleanups as needed. */ if (devnode->release) devnode->release (devnode);
@@ -283,6 +278,7 @@ void media_devnode_unregister(struct med/* Delete the cdev on this minor as well */ cdev_device_del (&devnode->cdev, &devnode->dev); devnode->media_dev =NULL ; +clear_bit (devnode->minor, media_devnode_nums);mutex_unlock (&media_devnode_lock);put_device (&devnode->dev);
Greg Kroah-Hartman
maintainerPATCH 231/276 mfd: intel_soc_pmic_chtdc_ti: Fix invalid regmap-config max_register value
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hans de Goede <[email protected]>
[ Upstream commit 70e997e0107e5ed85c1a3ef2adfccbe351c29d71 ]
The max_register = 128 setting in the regmap config is not valid.
The Intel Dollar Cove TI PMIC has an eeprom unlock register at address 0x88 and a number of EEPROM registers at 0xF?. Increase max_register to 0xff so that these registers can be accessed.
Stable-dep-of: 64e0d839c589 ("mfd: intel_soc_pmic_chtdc_ti: Set use_single_read regmap_config flag")
--- drivers/mfd/intel_soc_pmic_chtdc_ti.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/mfd/intel_soc_pmic_chtdc_ti.c +1 -1
@@ -81,7 +81,7 @@ static struct mfd_cell chtdc_ti_dev[] =static const struct regmap_config chtdc_ti_regmap_config = { .reg_bits =8 , .val_bits =8 , - .max_register =128 , + .max_register =0xff , .cache_type =REGCACHE_NONE , };
Greg Kroah-Hartman
maintainerPATCH 232/276 mfd: intel_soc_pmic_chtdc_ti: Drop unneeded assignment for cache_type
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andy Shevchenko <[email protected]>
[ Upstream commit 9eb99c08508714906db078b5efbe075329a3fb06 ]
REGCACHE_NONE is the default type of the cache when not provided. Drop unneeded explicit assignment to it.
Note, it's defined to 0, and if ever be redefined, it will break literally a lot of the drivers, so it very unlikely to happen.
Stable-dep-of: 64e0d839c589 ("mfd: intel_soc_pmic_chtdc_ti: Set use_single_read regmap_config flag")
--- drivers/mfd/intel_soc_pmic_chtdc_ti.c | 1 - 1 file changed, 1 deletion(-)
drivers/mfd/intel_soc_pmic_chtdc_ti.c +0 -1
@@ -82,7 +82,6 @@ static const struct regmap_config chtdc_ .reg_bits = 8, .val_bits = 8, .max_register = 0xff, - .cache_type = REGCACHE_NONE, };static const struct regmap_irq chtdc_ti_irqs[] = {
Greg Kroah-Hartman
maintainerPATCH 233/276 mfd: intel_soc_pmic_chtdc_ti: Set use_single_read regmap_config flag
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hans de Goede <[email protected]>
[ Upstream commit 64e0d839c589f4f2ecd2e3e5bdb5cee6ba6bade9 ]
Testing has shown that reading multiple registers at once (for 10-bit ADC values) does not work. Set the use_single_read regmap_config flag to make regmap split these for us.
This should fix temperature opregion accesses done by drivers/acpi/pmic/intel_pmic_chtdc_ti.c and is also necessary for the upcoming drivers for the ADC and battery MFD cells.
--- drivers/mfd/intel_soc_pmic_chtdc_ti.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/mfd/intel_soc_pmic_chtdc_ti.c +2 -0
@@ -82,6 +82,8 @@ static const struct regmap_config chtdc_ .reg_bits = 8, .val_bits = 8, .max_register = 0xff, + /* The hardware does not support reading multiple registers at once */ + .use_single_read = true, };static const struct regmap_irq chtdc_ti_irqs[] = {
Greg Kroah-Hartman
maintainerPATCH 234/276 net: usb: asix: hold PM usage ref to avoid PM/MDIO + RTNL deadlock
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Oleksij Rempel <[email protected]>
[ Upstream commit 3d3c4cd5c62f24bb3cb4511b7a95df707635e00a ]
Prevent USB runtime PM (autosuspend) for AX88772* in bind.
usbnet enables runtime PM (autosuspend) by default, so disabling it via the usb_driver flag is ineffective. On AX88772B, autosuspend shows no measurable power saving with current driver (no link partner, admin up/down). The ~0.453 W -> ~0.248 W drop on v6.1 comes from phylib powering the PHY off on admin-down, not from USB autosuspend.
The real hazard is that with runtime PM enabled, ndo_open() (under RTNL) may synchronously trigger autoresume (usb_autopm_get_interface()) into asix_resume() while the USB PM lock is held. Resume paths then invoke phylink/phylib and MDIO, which also expect RTNL, leading to possible deadlocks or PM lock vs MDIO wake issues.
To avoid this, keep the device runtime-PM active by taking a usage reference in ax88772_bind() and dropping it in unbind(). A non-zero PM usage count blocks runtime suspend regardless of userspace policy (.../power/control - pm_runtime_allow/forbid), making this approach robust against sysfs overrides.
Holding a runtime-PM usage ref does not affect system-wide suspend; system sleep/resume callbacks continue to run as before.
--- drivers/net/usb/asix_devices.c | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-)
drivers/net/usb/asix_devices.c +34 -1
@@ -608,6 +608,21 @@ static void ax88772_suspend(struct usbne asix_read_medium_status(dev, 1)); } +/* Notes on PM callbacks and locking context: +* +* - asix_suspend()/asix_resume() are invoked for both runtime PM and +* system-wide suspend/resume. For struct usb_driver the ->resume() +* callback does not receive pm_message_t, so the resume type cannot +* be distinguished here. +* +* - The MAC driver must hold RTNL when calling phylink interfaces such as +* phylink_suspend()/resume(). Those calls will also perform MDIO I/O. +* +* - Taking RTNL and doing MDIO from a runtime-PM resume callback (while +* the USB PM lock is held) is fragile. Since autosuspend brings no +* measurable power saving here, we block it by holding a PM usage +* reference in ax88772_bind(). +*/ static int asix_suspend (struct usb_interface *intf,pm_message_t message) {struct usbnet *dev =usb_get_intfdata (intf);
@@ -809,7 +824,18 @@ static int ax88772_bind(struct usbnet *dif (ret)return ret; -return ax88772_init_phy (dev); + ret =ax88772_init_phy (dev); +if (ret) +return ret; + +/* Keep this interface runtime-PM active by taking a usage ref. +* Prevents runtime suspend while bound and avoids resume paths +* that could deadlock (autoresume under RTNL while USB PM lock +* is held, phylink/MDIO wants RTNL). +*/ +pm_runtime_get_noresume (&intf->dev); + +return 0 ; }static int ax88772_stop (struct usbnet *dev)
@@ -827,6 +853,8 @@ static void ax88772_unbind(struct usbnetphy_disconnect (priv->phydev);asix_rx_fixup_common_free (dev->driver_priv); +/* Drop the PM usage ref taken in bind() */ +pm_runtime_put (&intf->dev); }static void ax88178_unbind (struct usbnet *dev,struct usb_interface *intf)
@@ -1452,6 +1480,11 @@ static struct usb_driver asix_driver = { .resume = asix_resume, .reset_resume = asix_resume, .disconnect = usbnet_disconnect, +/* usbnet enables autosuspend by default (supports_autosuspend=1). +* We keep runtime-PM active for AX88772* by taking a PM usage +* reference in ax88772_bind() (pm_runtime_get_noresume()) and +* dropping it in unbind(), which effectively blocks autosuspend. +*/ .supports_autosuspend = 1, .disable_hub_initiated_lpm = 1, };
Greg Kroah-Hartman
maintainerPATCH 235/276 ksmbd: fix error code overwriting in smb2_get_info_filesystem()
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matvey Kovalev <[email protected]>
[ Upstream commit 88daf2f448aad05a2e6df738d66fe8b0cf85cee0 ]
If client doesn't negotiate with SMB3.1.1 POSIX Extensions, then proper error code won't be returned due to overwriting.
Return error immediately.
Found by Linux Verification Center (linuxtesting.org) with SVACE.
--- fs/ksmbd/smb2pdu.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
fs/ksmbd/smb2pdu.c +2 -1
@@ -5204,7 +5204,8 @@ static int smb2_get_info_filesystem(struif (!work->tcon->posix_extensions) {pr_err ("client doesn't negotiate with SMB3.1.1 POSIX Extensions\n" ); - rc = -EOPNOTSUPP ; +path_put (&path); +return -EOPNOTSUPP ; }else { info = (struct filesystem_posix_info *)(rsp->Buffer); info->OptimalTransferSize =cpu_to_le32 (stfs.f_bsize);
Greg Kroah-Hartman
maintainerPATCH 236/276 tracing: Fix race condition in kprobe initialization causing NULL pointer dereference
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yuan Chen <[email protected]>
[ Upstream commit 9cf9aa7b0acfde7545c1a1d912576e9bab28dc6f ]
There is a critical race condition in kprobe initialization that can lead to NULL pointer dereference and kernel crash.
[1135630.084782] Unable to handle kernel paging request at virtual address 0000710a04630000 ... [1135630.260314] pstate: 404003c9 (nZcv DAIF +PAN -UAO) [1135630.269239] pc : kprobe_perf_func+0x30/0x260 [1135630.277643] lr : kprobe_dispatcher+0x44/0x60 [1135630.286041] sp : ffffaeff4977fa40 [1135630.293441] x29: ffffaeff4977fa40 x28: ffffaf015340e400 [1135630.302837] x27: 0000000000000000 x26: 0000000000000000 [1135630.312257] x25: ffffaf029ed108a8 x24: ffffaf015340e528 [1135630.321705] x23: ffffaeff4977fc50 x22: ffffaeff4977fc50 [1135630.331154] x21: 0000000000000000 x20: ffffaeff4977fc50 [1135630.340586] x19: ffffaf015340e400 x18: 0000000000000000 [1135630.349985] x17: 0000000000000000 x16: 0000000000000000 [1135630.359285] x15: 0000000000000000 x14: 0000000000000000 [1135630.368445] x13: 0000000000000000 x12: 0000000000000000 [1135630.377473] x11: 0000000000000000 x10: 0000000000000000 [1135630.386411] x9 : 0000000000000000 x8 : 0000000000000000 [1135630.395252] x7 : 0000000000000000 x6 : 0000000000000000 [1135630.403963] x5 : 0000000000000000 x4 : 0000000000000000 [1135630.412545] x3 : 0000710a04630000 x2 : 0000000000000006 [1135630.421021] x1 : ffffaeff4977fc50 x0 : 0000710a04630000 [1135630.429410] Call trace: [1135630.434828] kprobe_perf_func+0x30/0x260 [1135630.441661] kprobe_dispatcher+0x44/0x60 [1135630.448396] aggr_pre_handler+0x70/0xc8 [1135630.454959] kprobe_breakpoint_handler+0x140/0x1e0 [1135630.462435] brk_handler+0xbc/0xd8 [1135630.468437] do_debug_exception+0x84/0x138 [1135630.475074] el1_dbg+0x18/0x8c [1135630.480582] security_file_permission+0x0/0xd0 [1135630.487426] vfs_write+0x70/0x1c0 [1135630.493059] ksys_write+0x5c/0xc8 [1135630.498638] __arm64_sys_write+0x24/0x30 [1135630.504821] el0_svc_common+0x78/0x130 [1135630.510838] el0_svc_handler+0x38/0x78 [1135630.516834] el0_svc+0x8/0x1b0
kernel/trace/trace_kprobe.c: 13080xffff3df8995039ec <kprobe_perf_func+0x2c>: ldr x21, [x24,#120]include/linux/compiler.h: 2940xffff3df8995039f0 <kprobe_perf_func+0x30>: ldr x1, [x21,x0]
kernel/trace/trace_kprobe.c
1308: head = this_cpu_ptr(call->perf_events);
1309: if (hlist_empty(head))
1310: return 0;
crash> struct trace_event_call -o
struct trace_event_call {
...
[120] struct hlist_head *perf_events; //(call->perf_event)
...
}
crash> struct trace_event_call ffffaf015340e528
struct trace_event_call {
...
perf_events = 0xffff0ad5fa89f088, //this value is correct, but x21 = 0
...
}
Race Condition Analysis:
The race occurs between kprobe activation and perf_events initialization:
CPU0 CPU1
==== ====
perf_kprobe_init
perf_trace_event_init
tp_event->perf_events = list;(1)
tp_event->class->reg (2)← KPROBE ACTIVE
Debug exception triggers
...
kprobe_dispatcher
kprobe_perf_func (tk->tp.flags & TP_FLAG_PROFILE)
head = this_cpu_ptr(call->perf_events)(3)
(perf_events is still NULL)Problem:
1. CPU0 executes (1) assigning tp_event->perf_events = list
2. CPU0 executes (2) enabling kprobe functionality via class->reg()
3. CPU1 triggers and reaches kprobe_dispatcher
4. CPU1 checks TP_FLAG_PROFILE - condition passes (step 2 completed)
5. CPU1 calls kprobe_perf_func() and crashes at (3) because call->perf_events is still NULL
CPU1 sees that kprobe functionality is enabled but does not see that perf_events has been assigned.
Add pairing read and write memory barriers to guarantee that if CPU1 sees that kprobe functionality is enabled, it must also see that perf_events has been assigned.
--- kernel/trace/trace_kprobe.c | 11 +++++++---- kernel/trace/trace_probe.h | 9 +++++++-- kernel/trace/trace_uprobe.c | 12 ++++++++---- 3 files changed, 22 insertions(+), 10 deletions(-)
kernel/trace/trace_kprobe.c +7 -4
@@ -1722,14 +1722,15 @@ static int kprobe_register(struct trace_static int kprobe_dispatcher (struct kprobe *kp,struct pt_regs *regs) { struct trace_kprobe *tk = container_of(kp, struct trace_kprobe, rp.kp); +unsigned int flags =trace_probe_load_flag (&tk->tp);int ret =0 ;raw_cpu_inc (*tk->nhit); -if (trace_probe_test_flag (&tk->tp,TP_FLAG_TRACE )) +if (flags &TP_FLAG_TRACE )kprobe_trace_func (tk, regs);#ifdef CONFIG_PERF_EVENTS -if (trace_probe_test_flag (&tk->tp,TP_FLAG_PROFILE )) +if (flags &TP_FLAG_PROFILE ) ret =kprobe_perf_func (tk, regs);#endif return ret;
@@ -1741,6 +1742,7 @@ kretprobe_dispatcher(struct kretprobe_in {struct kretprobe *rp =get_kretprobe (ri);struct trace_kprobe *tk; +unsigned int flags;/* * There is a small chance that get_kretprobe(ri) returns NULL when
@@ -1753,10 +1755,11 @@ kretprobe_dispatcher(struct kretprobe_in tk = container_of(rp, struct trace_kprobe, rp);raw_cpu_inc (*tk->nhit); -if (trace_probe_test_flag (&tk->tp,TP_FLAG_TRACE )) + flags =trace_probe_load_flag (&tk->tp); +if (flags &TP_FLAG_TRACE )kretprobe_trace_func (tk, ri, regs);#ifdef CONFIG_PERF_EVENTS -if (trace_probe_test_flag (&tk->tp,TP_FLAG_PROFILE )) +if (flags &TP_FLAG_PROFILE )kretprobe_perf_func (tk, ri, regs);#endif return 0 ;/* We don't tweak kernel, so just return 0 */
kernel/trace/trace_probe.h +7 -2
@@ -258,16 +258,21 @@ struct event_file_link {struct list_head list; }; +static inline unsigned int trace_probe_load_flag (struct trace_probe *tp) +{ +return smp_load_acquire (&tp->event->flags); +} +static inline bool trace_probe_test_flag (struct trace_probe *tp,unsigned int flag) { -return !!(tp->event->flags & flag); +return !!(trace_probe_load_flag (tp) & flag); }static inline void trace_probe_set_flag (struct trace_probe *tp,unsigned int flag) { - tp->event->flags |= flag; +smp_store_release (&tp->event->flags, tp->event->flags | flag); } static inline void trace_probe_clear_flag(struct trace_probe *tp,
kernel/trace/trace_uprobe.c +8 -4
@@ -1485,6 +1485,7 @@ static int uprobe_dispatcher(struct uprostruct uprobe_dispatch_data udd;struct uprobe_cpu_buffer *ucb;int dsize, esize; +unsigned int flags;int ret =0 ;
@@ -1505,11 +1506,12 @@ static int uprobe_dispatcher(struct upro ucb =uprobe_buffer_get ();store_trace_args (ucb->buf, &tu->tp, regs, esize, dsize); -if (trace_probe_test_flag (&tu->tp,TP_FLAG_TRACE )) + flags =trace_probe_load_flag (&tu->tp); +if (flags &TP_FLAG_TRACE ) ret |=uprobe_trace_func (tu, regs, ucb, dsize);#ifdef CONFIG_PERF_EVENTS -if (trace_probe_test_flag (&tu->tp,TP_FLAG_PROFILE )) +if (flags &TP_FLAG_PROFILE ) ret |=uprobe_perf_func (tu, regs, ucb, dsize);#endif uprobe_buffer_put (ucb);
@@ -1523,6 +1525,7 @@ static int uretprobe_dispatcher(struct ustruct uprobe_dispatch_data udd;struct uprobe_cpu_buffer *ucb;int dsize, esize; +unsigned int flags; tu = container_of(con, struct trace_uprobe, consumer);
@@ -1540,11 +1543,12 @@ static int uretprobe_dispatcher(struct u ucb =uprobe_buffer_get ();store_trace_args (ucb->buf, &tu->tp, regs, esize, dsize); -if (trace_probe_test_flag (&tu->tp,TP_FLAG_TRACE )) + flags =trace_probe_load_flag (&tu->tp); +if (flags &TP_FLAG_TRACE )uretprobe_trace_func (tu, func, regs, ucb, dsize);#ifdef CONFIG_PERF_EVENTS -if (trace_probe_test_flag (&tu->tp,TP_FLAG_PROFILE )) +if (flags &TP_FLAG_PROFILE )uretprobe_perf_func (tu, func, regs, ucb, dsize);#endif uprobe_buffer_put (ucb);
Greg Kroah-Hartman
maintainerPATCH 237/276 dm: fix NULL pointer dereference in __dm_suspend()
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zheng Qixing <[email protected]>
[ Upstream commit 8d33a030c566e1f105cd5bf27f37940b6367f3be ]
There is a race condition between dm device suspend and table load that can lead to null pointer dereference. The issue occurs when suspend is invoked before table load completes:
BUG: kernel NULL pointer dereference, address: 0000000000000054 Oops: 0000 [#1] PREEMPT SMP PTI CPU: 6 PID: 6798 Comm: dmsetup Not tainted 6.6.0-g7e52f5f0ca9b #62 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.1-2.fc37 04/01/2014 RIP: 0010:blk_mq_wait_quiesce_done+0x0/0x50 Call Trace: <TASK> blk_mq_quiesce_queue+0x2c/0x50 dm_stop_queue+0xd/0x20 __dm_suspend+0x130/0x330 dm_suspend+0x11a/0x180 dev_suspend+0x27e/0x560 ctl_ioctl+0x4cf/0x850 dm_ctl_ioctl+0xd/0x20 vfs_ioctl+0x1d/0x50 __se_sys_ioctl+0x9b/0xc0 __x64_sys_ioctl+0x19/0x30 x64_sys_call+0x2c4a/0x4620 do_syscall_64+0x9e/0x1b0
The issue can be triggered as below:
T1 T2dm_suspend table_load__dm_suspend dm_setup_md_queue
dm_mq_init_request_queue blk_mq_init_allocated_queue => q->mq_ops = set->ops; (1) dm_stop_queue / dm_wait_for_completion => q->tag_set NULL pointer! (2) => q->tag_set = set; (3)
Fix this by checking if a valid table (map) exists before performing request-based suspend and waiting for target I/O. When map is NULL, skip these table-dependent suspend steps.
Even when map is NULL, no I/O can reach any target because there is no table loaded; I/O submitted in this state will fail early in the DM layer. Skipping the table-dependent suspend logic in this case is safe and avoids NULL pointer dereferences.
--- drivers/md/dm.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
drivers/md/dm.c +4 -3
@@ -2406,7 +2406,7 @@ static int __dm_suspend(struct mapped_de {bool do_lockfs = suspend_flags &DM_SUSPEND_LOCKFS_FLAG ;bool noflush = suspend_flags &DM_SUSPEND_NOFLUSH_FLAG ; -int r; +int r =0 ;lockdep_assert_held (&md->suspend_lock);
@@ -2458,7 +2458,7 @@ static int __dm_suspend(struct mapped_de* Stop md->queue before flushing md->wq in case request-based * dm defers requests to md->wq from md->queue. */ -if (dm_request_based (md)) +if (map &&dm_request_based (md))dm_stop_queue (md->queue);flush_workqueue (md->wq);
@@ -2468,7 +2468,8 @@ static int __dm_suspend(struct mapped_de* We call dm_wait_for_completion to wait for all existing requests * to finish. */ - r =dm_wait_for_completion (md, task_state); +if (map) + r =dm_wait_for_completion (md, task_state);if (!r)set_bit (dmf_suspended_flag, &md->flags);
Greg Kroah-Hartman
maintainerPATCH 238/276 locking: Introduce __cleanup() based infrastructure
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Peter Zijlstra <[email protected]>
[ Upstream commit 54da6a0924311c7cf5015533991e44fb8eb12773 ]
Use __attribute__((__cleanup__(func))) to build:
- simple auto-release pointers using __free()
- 'classes' with constructor and destructor semantics for scope-based resource management.
- lock guards based on the above classes.
--- drivers/dma/ioat/dma.c | 12 +- include/linux/cleanup.h | 171 ++++++++++++++++++++++++++++++++++++ include/linux/compiler-clang.h | 9 + include/linux/compiler_attributes.h | 6 + include/linux/device.h | 7 + include/linux/file.h | 6 + include/linux/irqflags.h | 7 + include/linux/mutex.h | 4 include/linux/percpu.h | 4 include/linux/preempt.h | 47 +++++++++ include/linux/rcupdate.h | 3 include/linux/rwsem.h | 8 + include/linux/sched/task.h | 2 include/linux/slab.h | 3 include/linux/spinlock.h | 32 ++++++ include/linux/srcu.h | 5 + scripts/checkpatch.pl | 2 17 files changed, 321 insertions(+), 7 deletions(-) create mode 100644 include/linux/cleanup.h
drivers/dma/ioat/dma.c +6 -6
@@ -584,11 +584,11 @@ desc_get_errstat(struct ioatdma_chan *io }/** -* __cleanup - reclaim used descriptors +* __ioat_cleanup - reclaim used descriptors * @ioat_chan: channel (ring) to clean * @phys_complete: zeroed (or not) completion address (from status) */ -static void __cleanup (struct ioatdma_chan *ioat_chan,dma_addr_t phys_complete) +static void __ioat_cleanup (struct ioatdma_chan *ioat_chan,dma_addr_t phys_complete) {struct ioatdma_device *ioat_dma = ioat_chan->ioat_dma;struct ioat_ring_ent *desc;
@@ -675,7 +675,7 @@ static void ioat_cleanup(struct ioatdma_spin_lock_bh (&ioat_chan->cleanup_lock);if (ioat_cleanup_preamble (ioat_chan, &phys_complete)) -__cleanup (ioat_chan, phys_complete); +__ioat_cleanup (ioat_chan, phys_complete);if (is_ioat_halted (*ioat_chan->completion)) {u32 chanerr =readl (ioat_chan->reg_base +IOAT_CHANERR_OFFSET );
@@ -712,7 +712,7 @@ static void ioat_restart_channel(structioat_quiesce (ioat_chan,0 );if (ioat_cleanup_preamble (ioat_chan, &phys_complete)) -__cleanup (ioat_chan, phys_complete); +__ioat_cleanup (ioat_chan, phys_complete);__ioat_restart_chan (ioat_chan); }
@@ -786,7 +786,7 @@ static void ioat_eh(struct ioatdma_chan/* cleanup so tail points to descriptor that caused the error */ if (ioat_cleanup_preamble (ioat_chan, &phys_complete)) -__cleanup (ioat_chan, phys_complete); +__ioat_cleanup (ioat_chan, phys_complete); chanerr =readl (ioat_chan->reg_base +IOAT_CHANERR_OFFSET );pci_read_config_dword (pdev,IOAT_PCI_CHANERR_INT_OFFSET , &chanerr_int);
@@ -943,7 +943,7 @@ void ioat_timer_event(struct timer_list/* timer restarted in ioat_cleanup_preamble * and IOAT_COMPLETION_ACK cleared */ -__cleanup (ioat_chan, phys_complete); +__ioat_cleanup (ioat_chan, phys_complete); goto unlock_out; }
include/linux/cleanup.h new file +171 -0
171 lines not on this page · raw message
include/linux/compiler-clang.h +9 -0
@@ -5,6 +5,15 @@/* Compiler specific definitions for Clang compiler */ +/* +* Clang prior to 17 is being silly and considers many __cleanup() variables +* as unused (because they are, their sole purpose is to go out of scope). +* +* https://reviews.llvm.org/D152180 +*/ +#undef __cleanup +#define __cleanup (func) __maybe_unused __attribute__((__cleanup__(func))) +/* same as gcc, this was present in clang-2.6 so we can assume it works * with any version that can compile the kernel */
include/linux/compiler_attributes.h +6 -0
@@ -81,6 +81,12 @@#define __cold __attribute__((__cold__))/* +* gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#index-cleanup-variable-attribute +* clang: https://clang.llvm.org/docs/AttributeReference.html#cleanup +*/ +#define __cleanup (func) __attribute__((__cleanup__(func))) + +/* * Note the long name. * * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-const-function-attribute
include/linux/device.h +7 -0
@@ -30,6 +30,7 @@#include <linux/device/bus.h> #include <linux/device/class.h> #include <linux/device/driver.h> +#include <linux/cleanup.h> #include <asm/device.h> struct device ;
@@ -825,6 +826,9 @@ void device_unregister(struct device *devoid device_initialize (struct device *dev);int __must_check device_add (struct device *dev);void device_del (struct device *dev); + +DEFINE_FREE(device_del, struct device *, if (_T) device_del(_T)) +int device_for_each_child (struct device *dev,void *data,int (*fn)(struct device *dev,void *data)); int device_for_each_child_reverse(struct device *dev, void *data,
@@ -955,6 +959,9 @@ extern int (*platform_notify_remove)(str*/ struct device *get_device (struct device *dev);void put_device (struct device *dev); + +DEFINE_FREE(put_device, struct device *, if (_T) put_device(_T)) +bool kill_device (struct device *dev);#ifdef CONFIG_DEVTMPFS
include/linux/file.h +6 -0
@@ -10,6 +10,7 @@#include <linux/types.h> #include <linux/posix_types.h> #include <linux/errno.h> +#include <linux/cleanup.h> struct file ;
@@ -82,6 +83,8 @@ static inline void fdput_pos(struct fd ffdput (f); } +DEFINE_CLASS(fd, struct fd, fdput(_T), fdget(fd), int fd) +extern int f_dupfd (unsigned int from,struct file *file,unsigned flags);extern int replace_fd (unsigned fd,struct file *file,unsigned flags);extern void set_close_on_exec (unsigned int fd,int flag);
@@ -90,6 +93,9 @@ extern int __get_unused_fd_flags(unsigneextern int get_unused_fd_flags (unsigned flags);extern void put_unused_fd (unsigned int fd); +DEFINE_CLASS(get_unused_fd, int, if (_T >= 0) put_unused_fd(_T), + get_unused_fd_flags(flags), unsigned flags) +extern void fd_install (unsigned int fd,struct file *file); extern int __receive_fd(struct file *file, int __user *ufd,
include/linux/irqflags.h +7 -0
@@ -13,6 +13,7 @@#define _LINUX_TRACE_IRQFLAGS_H#include <linux/typecheck.h> +#include <linux/cleanup.h> #include <asm/irqflags.h> #include <asm/percpu.h>
@@ -260,4 +261,10 @@ extern void warn_bogus_irq_restore(void)#define irqs_disabled_flags (flags) raw_irqs_disabled_flags(flags) +DEFINE_LOCK_GUARD_0(irq, local_irq_disable(), local_irq_enable()) +DEFINE_LOCK_GUARD_0 (irqsave, +local_irq_save (_T->flags), +local_irq_restore (_T->flags), + unsigned long flags) +#endif
include/linux/mutex.h +4 -0
@@ -19,6 +19,7 @@#include <asm/processor.h> #include <linux/osq_lock.h> #include <linux/debug_locks.h> +#include <linux/cleanup.h> struct device ;
@@ -246,4 +247,7 @@ extern void mutex_unlock(struct mutex *lextern int atomic_dec_and_mutex_lock (atomic_t *cnt,struct mutex *lock); +DEFINE_GUARD(mutex, struct mutex *, mutex_lock(_T), mutex_unlock(_T)) +DEFINE_FREE(mutex, struct mutex *, if (_T) mutex_unlock(_T)) +#endif /* __LINUX_MUTEX_H */
include/linux/percpu.h +4 -0
@@ -9,6 +9,7 @@#include <linux/printk.h> #include <linux/pfn.h> #include <linux/init.h> +#include <linux/cleanup.h> #include <asm/percpu.h>
@@ -134,6 +135,9 @@ extern void __init setup_per_cpu_areas(vextern void __percpu *__alloc_percpu_gfp (size_t size,size_t align,gfp_t gfp);extern void __percpu *__alloc_percpu (size_t size,size_t align);extern void free_percpu (void __percpu *__pdata); + +DEFINE_FREE(free_percpu, void __percpu *, free_percpu(_T)) +extern phys_addr_t per_cpu_ptr_to_phys (void *addr);#define alloc_percpu_gfp (type, gfp) \
include/linux/preempt.h +47 -0
57 lines not on this page · raw message
include/linux/rcupdate.h +3 -0
@@ -27,6 +27,7 @@#include <linux/preempt.h> #include <linux/bottom_half.h> #include <linux/lockdep.h> +#include <linux/cleanup.h> #include <asm/processor.h> #include <linux/cpumask.h>
@@ -1060,4 +1061,6 @@ rcu_head_after_call_rcu(struct rcu_headextern int rcu_expedited;extern int rcu_normal; +DEFINE_LOCK_GUARD_0(rcu, rcu_read_lock(), rcu_read_unlock()) +#endif /* __LINUX_RCUPDATE_H */
include/linux/rwsem.h +8 -0
@@ -16,6 +16,7 @@#include <linux/spinlock.h> #include <linux/atomic.h> #include <linux/err.h> +#include <linux/cleanup.h> #ifdef CONFIG_DEBUG_LOCK_ALLOC # define __RWSEM_DEP_MAP_INIT (lockname) \
@@ -202,6 +203,13 @@ extern void up_read(struct rw_semaphore*/ extern void up_write (struct rw_semaphore *sem); +DEFINE_GUARD(rwsem_read, struct rw_semaphore *, down_read(_T), up_read(_T)) +DEFINE_GUARD(rwsem_write, struct rw_semaphore *, down_write(_T), up_write(_T)) + +DEFINE_FREE(up_read, struct rw_semaphore *, if (_T) up_read(_T)) +DEFINE_FREE(up_write, struct rw_semaphore *, if (_T) up_write(_T)) + +/* * downgrade write lock to read lock */
include/linux/sched/task.h +2 -0
@@ -142,6 +142,8 @@ static inline void put_task_struct(struc__put_task_struct (t); } +DEFINE_FREE(put_task, struct task_struct *, if (_T) put_task_struct(_T)) +static inline void put_task_struct_many (struct task_struct *t,int nr) {if (refcount_sub_and_test (nr, &t->usage))
include/linux/slab.h +3 -0
@@ -17,6 +17,7 @@#include <linux/types.h> #include <linux/workqueue.h> #include <linux/percpu-refcount.h> +#include <linux/cleanup.h> /*
@@ -186,6 +187,8 @@ void kfree(const void *objp);void kfree_sensitive (const void *objp);size_t __ksize (const void *objp); +DEFINE_FREE(kfree, void *, if (_T) kfree(_T)) +/** * ksize - Report actual allocation size of associated object *
include/linux/spinlock.h +32 -0
@@ -61,6 +61,7 @@#include <linux/stringify.h> #include <linux/bottom_half.h> #include <linux/lockdep.h> +#include <linux/cleanup.h> #include <asm/barrier.h> #include <asm/mmiowb.h>
@@ -506,4 +507,35 @@ int __alloc_bucket_spinlocks(spinlock_tvoid free_bucket_spinlocks (spinlock_t *locks); +DEFINE_LOCK_GUARD_1 (raw_spinlock, raw_spinlock_t, +raw_spin_lock (_T->lock), + raw_spin_unlock(_T->lock)) + +DEFINE_LOCK_GUARD_1 (raw_spinlock_nested, raw_spinlock_t, +raw_spin_lock_nested (_T->lock,SINGLE_DEPTH_NESTING ), + raw_spin_unlock(_T->lock)) + +DEFINE_LOCK_GUARD_1 (raw_spinlock_irq, raw_spinlock_t, +raw_spin_lock_irq (_T->lock), + raw_spin_unlock_irq(_T->lock)) + +DEFINE_LOCK_GUARD_1 (raw_spinlock_irqsave, raw_spinlock_t, +raw_spin_lock_irqsave (_T->lock, _T->flags), +raw_spin_unlock_irqrestore (_T->lock, _T->flags), + unsigned long flags) + +DEFINE_LOCK_GUARD_1 (spinlock, spinlock_t, +spin_lock (_T->lock), + spin_unlock(_T->lock)) + +DEFINE_LOCK_GUARD_1 (spinlock_irq, spinlock_t, +spin_lock_irq (_T->lock), + spin_unlock_irq(_T->lock)) + +DEFINE_LOCK_GUARD_1 (spinlock_irqsave, spinlock_t, +spin_lock_irqsave (_T->lock, _T->flags), +spin_unlock_irqrestore (_T->lock, _T->flags), + unsigned long flags) + +#undef __LINUX_INSIDE_SPINLOCK_H#endif /* __LINUX_SPINLOCK_H */
include/linux/srcu.h +5 -0
@@ -211,4 +211,9 @@ static inline void smp_mb__after_srcu_re/* __srcu_read_unlock has smp_mb() internally so nothing to do here. */ } +DEFINE_LOCK_GUARD_1(srcu, struct srcu_struct, + _T->idx = srcu_read_lock(_T->lock), + srcu_read_unlock(_T->lock, _T->idx), + int idx) +#endif
scripts/checkpatch.pl +1 -1
@@ -4895,7 +4895,7 @@ sub process { if|for|while|switch|return|case| volatile|__volatile__| __attribute__|format|__extension__| - asm|__asm__)$/x) + asm|__asm__|scoped_guard)$/x) { # cpp #define statements have non-optional spaces, ie # if there is a space between the name and the open
Greg Kroah-Hartman
maintainerPATCH 239/276 fscontext: do not consume log entries when returning -EMSGSIZE
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aleksa Sarai <[email protected]>
[ Upstream commit 72d271a7baa7062cb27e774ac37c5459c6d20e22 ]
Userspace generally expects APIs that return -EMSGSIZE to allow for them to adjust their buffer size and retry the operation. However, the fscontext log would previously clear the message even in the -EMSGSIZE case.
Given that it is very cheap for us to check whether the buffer is too small before we remove the message from the ring buffer, let's just do that instead. While we're at it, refactor some fscontext_read() into a separate helper to make the ring buffer logic a bit easier to read.
--- fs/fsopen.c | 70 ++++++++++++++++++++++++++++++++---------------------------- 1 file changed, 38 insertions(+), 32 deletions(-)
fs/fsopen.c +38 -32
@@ -18,50 +18,56 @@#include "internal.h" #include "mount.h" +static inline const char *fetch_message_locked (struct fc_log *log,size_t len, +bool *need_free) +{ +const char *p; +int index; + +if (unlikely (log->head == log->tail)) +return ERR_PTR (-ENODATA ); + + index = log->tail & (ARRAY_SIZE (log->buffer) -1 ); + p = log->buffer[index]; +if (unlikely (strlen (p) > len)) +return ERR_PTR (-EMSGSIZE ); + + log->buffer[index] =NULL ; + *need_free = log->need_free & (1 << index); + log->need_free &= ~(1 << index); + log->tail++; + +return p; +} +/* * Allow the user to read back any error, warning or informational messages. +* Only one message is returned for each read(2) call. */ static ssize_t fscontext_read (struct file *file,char __user *_buf,size_t len,loff_t *pos) {struct fs_context *fc = file->private_data; -struct fc_log *log = fc->log.log; -unsigned int logsize =ARRAY_SIZE (log->buffer); -ssize_t ret; -char *p; +ssize_t err; + const char *p __free(kfree) = NULL, *message;bool need_free; -int index, n; - - ret =mutex_lock_interruptible (&fc->uapi_mutex); -if (ret <0 ) -return ret; - -if (log->head == log->tail) { -mutex_unlock (&fc->uapi_mutex); -return -ENODATA ; - } +int n; - index = log->tail & (logsize -1 ); - p = log->buffer[index]; - need_free = log->need_free & (1 << index); - log->buffer[index] =NULL ; - log->need_free &= ~(1 << index); - log->tail++; + err =mutex_lock_interruptible (&fc->uapi_mutex); +if (err <0 ) +return err; + message =fetch_message_locked (fc->log.log, len, &need_free);mutex_unlock (&fc->uapi_mutex); +if (IS_ERR (message)) +return PTR_ERR (message); - ret = -EMSGSIZE ; - n =strlen (p); -if (n > len) - goto err_free; - ret = -EFAULT ; -if (copy_to_user (_buf, p, n) !=0 ) - goto err_free; - ret = n; - -err_free:if (need_free) -kfree (p); -return ret; + p = message; + + n =strlen (message); +if (copy_to_user (_buf, message, n)) +return -EFAULT ; +return n; }static int fscontext_release (struct inode *inode,struct file *file)
Greg Kroah-Hartman
maintainerPATCH 240/276 btrfs: fix the incorrect max_bytes value for find_lock_delalloc_range()
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Qu Wenruo <[email protected]>
[ Upstream commit 7b26da407420e5054e3f06c5d13271697add9423 ]
[BUG]
With my local branch to enable bs > ps support for btrfs, sometimes I hit the following ASSERT() inside submit_one_sector():
ASSERT(block_start != EXTENT_MAP_HOLE);
Please note that it's not yet possible to hit this ASSERT() in the wild yet, as it requires btrfs bs > ps support, which is not even in the development branch.
But on the other hand, there is also a very low chance to hit above ASSERT() with bs < ps cases, so this is an existing bug affect not only the incoming bs > ps support but also the existing bs < ps support.
[CAUSE]
Firstly that ASSERT() means we're trying to submit a dirty block but without a real extent map nor ordered extent map backing it.
Furthermore with extra debugging, the folio triggering such ASSERT() is always larger than the fs block size in my bs > ps case.
(8K block size, 4K page size)
After some more debugging, the ASSERT() is trigger by the following sequence:
extent_writepage()
| We got a 32K folio (4 fs blocks) at file offset 0, and the fs block
| size is 8K, page size is 4K.
| And there is another 8K folio at file offset 32K, which is also
| dirty.
| So the filemap layout looks like the following:
|
| "||" is the filio boundary in the filemap.
| "//| is the dirty range.
|
| 0 8K 16K 24K 32K 40K
| |////////| |//////////////////////||////////|
|
|- writepage_delalloc()
| |- find_lock_delalloc_range() for [0, 8K)
| | Now range [0, 8K) is properly locked.
| |
| |- find_lock_delalloc_range() for [16K, 40K)
| | |- btrfs_find_delalloc_range() returned range [16K, 40K)
| | |- lock_delalloc_folios() locked folio 0 successfully
| | |
| | | The filemap range [32K, 40K) got dropped from filemap.
| | |
| | |- lock_delalloc_folios() failed with -EAGAIN on folio 32K
| | | As the folio at 32K is dropped.
| | |
| | |- loops = 1;
| | |- max_bytes = PAGE_SIZE;
| | |- goto again;
| | | This will re-do the lookup for dirty delalloc ranges.
| | |
| | |- btrfs_find_delalloc_range() called with @max_bytes == 4K
| | | This is smaller than block size, so
| | | btrfs_find_delalloc_range() is unable to return any range.
| | \- return false;
| |
| \- Now only range [0, 8K) has an OE for it, but for dirty range
| [16K, 32K) it's dirty without an OE.
| This breaks the assumption that writepage_delalloc() will find
| and lock all dirty ranges inside the folio.
|
|- extent_writepage_io()
|- submit_one_sector() for [0, 8K)
| Succeeded
|
|- submit_one_sector() for [16K, 24K) Triggering the ASSERT(), as there is no OE, and the original extent map is a hole.
Please note that, this also exposed the same problem for bs < ps support. E.g. with 64K page size and 4K block size.
If we failed to lock a folio, and falls back into the "loops = 1;" branch, we will re-do the search using 64K as max_bytes. Which may fail again to lock the next folio, and exit early without handling all dirty blocks inside the folio.
[FIX]
Instead of using the fixed size PAGE_SIZE as @max_bytes, use @sectorsize, so that we are ensured to find and lock any remaining blocks inside the folio.
And since we're here, add an extra ASSERT() to
before calling btrfs_find_delalloc_range() to make sure the @max_bytes is at least no smaller than a block to avoid false negative.
--- fs/btrfs/extent_io.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-)
fs/btrfs/extent_io.c +11 -3
@@ -2000,6 +2000,13 @@ again:/* step one, find a bunch of delalloc bytes starting at start */ delalloc_start = *start; delalloc_end =0 ; + +/* +* If @max_bytes is smaller than a block, btrfs_find_delalloc_range() can +* return early without handling any dirty ranges. +*/ +ASSERT (max_bytes >= fs_info->sectorsize); + found =btrfs_find_delalloc_range (tree, &delalloc_start, &delalloc_end, max_bytes, &cached_state);if (!found || delalloc_end <= *start) {
@@ -2028,13 +2035,14 @@ again: delalloc_start, delalloc_end);ASSERT (!ret || ret == -EAGAIN );if (ret == -EAGAIN ) { -/* some of the pages are gone, lets avoid looping by -* shortening the size of the delalloc range we're searching +/* +* Some of the pages are gone, lets avoid looping by +* shortening the size of the delalloc range we're searching. */ free_extent_state (cached_state); cached_state =NULL ;if (!loops) { - max_bytes =PAGE_SIZE ; + max_bytes = fs_info->sectorsize; loops =1 ; goto again; }else {
Greg Kroah-Hartman
maintainerPATCH 241/276 arm64: dts: qcom: sdm845: Fix slimbam num-channels/ees
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Stephan Gerhold <[email protected]>
[ Upstream commit 316294bb6695a43a9181973ecd4e6fb3e576a9f7 ]
Reading the hardware registers of the &slimbam on RB3 reveals that the BAM supports only 23 pipes (channels) and supports 4 EEs instead of 2. This hasn't caused problems so far since nothing is using the extra channels, but attempting to use them would lead to crashes.
The bam_dma driver might warn in the future if the num-channels in the DT are wrong, so correct the properties in the DT to avoid future regressions.
--- arch/arm64/boot/dts/qcom/sdm845.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/arm64/boot/dts/qcom/sdm845.dtsi +2 -2
@@ -4839,11 +4839,11 @@ compatible = "qcom,bam-v1.7.0"; qcom,controlled-remotely; reg = <0 0x17184000 0 0x2a000>; - num-channels = <31>; + num-channels = <23>; interrupts = <GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>; #dma-cells = <1>; qcom,ee = <1>; - qcom,num-ees = <2>; + qcom,num-ees = <4>; iommus = <&apps_smmu 0x1806 0x0>; };
Greg Kroah-Hartman
maintainerPATCH 242/276 minmax: Introduce {min,max}_array()
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Herve Codina <[email protected]>
[ Upstream commit c952c748c7a983a8bda9112984e6f2c1f6e441a5 ]
Introduce min_array() (resp max_array()) in order to get the minimal (resp maximum) of values present in an array.
--- include/linux/minmax.h | 64 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+)
include/linux/minmax.h +64 -0
@@ -168,6 +168,70 @@*/ #define max_t (type, x, y) __careful_cmp(max, (type)(x), (type)(y)) +/* +* Remove a const qualifier from integer types +* _Generic(foo, type-name: association, ..., default: association) performs a +* comparison against the foo type (not the qualified type). +* Do not use the const keyword in the type-name as it will not match the +* unqualified type of foo. +*/ +#define __unconst_integer_type_cases (type) \ + unsigned type: (unsigned type)0, \ + signed type: (signed type)0 + +#define __unconst_integer_typeof (x) typeof( \ + _Generic((x), \ + char: (char)0, \ + __unconst_integer_type_cases(char), \ + __unconst_integer_type_cases(short), \ + __unconst_integer_type_cases(int), \ + __unconst_integer_type_cases(long), \ + __unconst_integer_type_cases(long long), \ + default: (x))) + +/* +* Do not check the array parameter using __must_be_array(). +* In the following legit use-case where the "array" passed is a simple pointer, +* __must_be_array() will return a failure. +* --- 8< --- +* int *buff +* ... +* min = min_array(buff, nb_items); +* --- 8< --- +* +* The first typeof(&(array)[0]) is needed in order to support arrays of both +* 'int *buff' and 'int buff[N]' types. +* +* The array can be an array of const items. +* typeof() keeps the const qualifier. Use __unconst_integer_typeof() in order +* to discard the const qualifier for the __element variable. +*/ +#define __minmax_array (op, array, len) ({ \ + typeof(&(array)[0]) __array = (array); \ + typeof(len) __len = (len); \ + __unconst_integer_typeof(__array[0]) __element = __array[--__len]; \ + while (__len--) \ + __element = op(__element, __array[__len]); \ + __element; }) + +/** +* min_array - return minimum of values present in an array +* @array: array +* @len: array length +* +* Note that @len must not be zero (empty array). +*/ +#define min_array (array, len) __minmax_array(min, array, len) + +/** +* max_array - return maximum of values present in an array +* @array: array +* @len: array length +* +* Note that @len must not be zero (empty array). +*/ +#define max_array (array, len) __minmax_array(max, array, len) +/** * clamp_t - return a value clamped to a given range using a given type * @type: the type of variable to use
Greg Kroah-Hartman
maintainerPATCH 243/276 minmax: deduplicate __unconst_integer_typeof()
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andy Shevchenko <[email protected]>
[ Upstream commit 5e57418a2031cd5e1863efdf3d7447a16a368172 ]
It appears that compiler_types.h already have an implementation of the __unconst_integer_typeof() called __unqual_scalar_typeof(). Use it instead of the copy.
--- include/linux/minmax.h | 25 ++----------------------- 1 file changed, 2 insertions(+), 23 deletions(-)
include/linux/minmax.h +2 -23
@@ -169,27 +169,6 @@#define max_t (type, x, y) __careful_cmp(max, (type)(x), (type)(y))/* -* Remove a const qualifier from integer types -* _Generic(foo, type-name: association, ..., default: association) performs a -* comparison against the foo type (not the qualified type). -* Do not use the const keyword in the type-name as it will not match the -* unqualified type of foo. -*/ -#define __unconst_integer_type_cases (type) \ - unsigned type: (unsigned type)0, \ - signed type: (signed type)0 - -#define __unconst_integer_typeof (x) typeof( \ - _Generic((x), \ - char: (char)0, \ - __unconst_integer_type_cases(char), \ - __unconst_integer_type_cases(short), \ - __unconst_integer_type_cases(int), \ - __unconst_integer_type_cases(long), \ - __unconst_integer_type_cases(long long), \ - default: (x))) - -/* * Do not check the array parameter using __must_be_array(). * In the following legit use-case where the "array" passed is a simple pointer, * __must_be_array() will return a failure.
@@ -203,13 +182,13 @@* 'int *buff' and 'int buff[N]' types. * * The array can be an array of const items. -* typeof() keeps the const qualifier. Use __unconst_integer_typeof() in order +* typeof() keeps the const qualifier. Use __unqual_scalar_typeof() in order * to discard the const qualifier for the __element variable. */ #define __minmax_array (op, array, len) ({ \ typeof(&(array)[0]) __array = (array); \ typeof(len) __len = (len); \ - __unconst_integer_typeof(__array[0]) __element = __array[--__len]; \ + __unqual_scalar_typeof(__array[0]) __element = __array[--__len];\ while (__len--) \ __element = op(__element, __array[__len]); \ __element; })
Greg Kroah-Hartman
maintainerPATCH 244/276 minmax: fix indentation of __cmp_once() and __clamp_once()
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Laight <[email protected]>
[ Upstream commit f4b84b2ff851f01d0fac619eadef47eb41648534 ]
Remove the extra indentation and align continuation markers.
--- include/linux/minmax.h | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-)
include/linux/minmax.h +15 -15
@@ -46,11 +46,11 @@#define __cmp (op, x, y) ((x) __cmp_op_##op (y) ? (x) : (y))#define __cmp_once (op, x, y, unique_x, unique_y) ({ \ - typeof(x) unique_x = (x); \ - typeof(y) unique_y = (y); \ - static_assert(__types_ok(x, y), \ - #op "(" #x ", " #y ") signedness error, fix types or consider u" #op "() before " #op "_t()"); \ - __cmp(op, unique_x, unique_y); }) + typeof(x) unique_x = (x); \ + typeof(y) unique_y = (y); \ + static_assert(__types_ok(x, y), \ + #op "(" #x ", " #y ") signedness error, fix types or consider u" #op "() before " #op "_t()"); \ + __cmp(op, unique_x, unique_y); })#define __careful_cmp (op, x, y) \ __builtin_choose_expr(__is_constexpr((x) - (y)), \
@@ -60,16 +60,16 @@#define __clamp (val, lo, hi) \ ((val) >= (hi) ? (hi) : ((val) <= (lo) ? (lo) : (val))) -#define __clamp_once (val, lo, hi, unique_val, unique_lo, unique_hi) ({ \ - typeof(val) unique_val = (val); \ - typeof(lo) unique_lo = (lo); \ - typeof(hi) unique_hi = (hi); \ - static_assert(__builtin_choose_expr(__is_constexpr((lo) > (hi)), \ - (lo) <= (hi), true), \ - "clamp() low limit " #lo " greater than high limit " #hi); \ - static_assert(__types_ok(val, lo), "clamp() 'lo' signedness error"); \ - static_assert(__types_ok(val, hi), "clamp() 'hi' signedness error"); \ - __clamp(unique_val, unique_lo, unique_hi); }) +#define __clamp_once (val, lo, hi, unique_val, unique_lo, unique_hi) ({ \ + typeof(val) unique_val = (val); \ + typeof(lo) unique_lo = (lo); \ + typeof(hi) unique_hi = (hi); \ + static_assert(__builtin_choose_expr(__is_constexpr((lo) > (hi)), \ + (lo) <= (hi), true), \ + "clamp() low limit " #lo " greater than high limit " #hi); \ + static_assert(__types_ok(val, lo), "clamp() 'lo' signedness error"); \ + static_assert(__types_ok(val, hi), "clamp() 'hi' signedness error"); \ + __clamp(unique_val, unique_lo, unique_hi); })#define __careful_clamp (val, lo, hi) ({ \ __builtin_choose_expr(__is_constexpr((val) - (lo) + (hi)), \
Greg Kroah-Hartman
maintainerPATCH 245/276 minmax: avoid overly complicated constant expressions in VM code
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Linus Torvalds <[email protected]>
[ Upstream commit 3a7e02c040b130b5545e4b115aada7bacd80a2b6 ]
The minmax infrastructure is overkill for simple constants, and can cause huge expansions because those simple constants are then used by other things.
For example, 'pageblock_order' is a core VM constant, but because it was implemented using 'min_t()' and all the type-checking that involves, it actually expanded to something like 2.5kB of preprocessor noise.
And when that simple constant was then used inside other expansions:
#define pageblock_nr_pages (1UL << pageblock_order) #define pageblock_start_pfn(pfn) ALIGN_DOWN((pfn), pageblock_nr_pages)
and we then use that inside a 'max()' macro:
case ISOLATE_SUCCESS: update_cached = false; last_migrated_pfn = max(cc->zone->zone_start_pfn, pageblock_start_pfn(cc->migrate_pfn - 1));
the end result was that one statement expanding to 253kB in size.
There are probably other cases of this, but this one case certainly stood out.
I've added 'MIN_T()' and 'MAX_T()' macros for this kind of "core simple constant with specific type" use. These macros skip the type checking, and as such need to be very sparingly used only for obvious cases that have active issues like this.
--- include/linux/minmax.h | 7 +++++++ 1 file changed, 7 insertions(+)
include/linux/minmax.h +7 -0
@@ -270,4 +270,11 @@ static inline bool in_range32(u32 val, u#define swap (a, b) \ do { typeof(a) __tmp = (a); (a) = (b); (b) = __tmp; } while (0) +/* +* Use these carefully: no type checking, and uses the arguments +* multiple times. Use for obvious constants only. +*/ +#define MIN_T (type,a,b) __cmp(min,(type)(a),(type)(b)) +#define MAX_T (type,a,b) __cmp(max,(type)(a),(type)(b)) +#endif /* _LINUX_MINMAX_H */
Greg Kroah-Hartman
maintainerPATCH 246/276 minmax: add a few more MIN_T/MAX_T users
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Linus Torvalds <[email protected]>
[ Upstream commit 4477b39c32fdc03363affef4b11d48391e6dc9ff ]
Commit 3a7e02c040b1 ("minmax: avoid overly complicated constant expressions in VM code") added the simpler MIN_T/MAX_T macros in order to avoid some excessive expansion from the rather complicated regular min/max macros.
The complexity of those macros stems from two issues:
(a) trying to use them in situations that require a C constant expression (in static initializers and for array sizes)
(b) the type sanity checking
and MIN_T/MAX_T avoids both of these issues.
Now, in the whole (long) discussion about all this, it was pointed out that the whole type sanity checking is entirely unnecessary for min_t/max_t which get a fixed type that the comparison is done in.
But that still leaves min_t/max_t unnecessarily complicated due to worries about the C constant expression case.
However, it turns out that there really aren't very many cases that use min_t/max_t for this, and we can just force-convert those.
This does exactly that.
Which in turn will then allow for much simpler implementations of min_t()/max_t(). All the usual "macros in all upper case will evaluate the arguments multiple times" rules apply.
We should do all the same things for the regular min/max() vs MIN/MAX() cases, but that has the added complexity of various drivers defining their own local versions of MIN/MAX, so that needs another level of fixes first.
---
V2 -> V3:
Fix fs/erofs/zdata.h to use MIN_T instead of min_t to fix build on the following patch:
In file included from ./include/linux/kernel.h:16,
from ./include/linux/list.h:9,
from ./include/linux/wait.h:7,
from ./include/linux/wait_bit.h:8,
from ./include/linux/fs.h:6,
from fs/erofs/internal.h:10,
from fs/erofs/zdata.h:9,
from fs/erofs/zdata.c:6:fs/erofs/zdata.c: In function ‘z_erofs_decompress_pcluster’:fs/erofs/zdata.h:185:61: error: ISO C90 forbids variable length array ‘pages_onstack’ [-Werror=vla]
185 | min_t(unsigned int, THREAD_SIZE / 8 / sizeof(struct page *), 96U)
| ^~~~./include/linux/minmax.h:49:23: note: in definition of macro ‘__cmp_once_unique’
49 | ({ type ux = (x); type uy = (y); __cmp(op, ux, uy); })
| ^./include/linux/minmax.h:164:27: note: in expansion of macro ‘__cmp_once’
164 | #define min_t(type, x, y) __cmp_once(min, type, x, y)
| ^~~~~~~~~~
fs/erofs/zdata.h:185:9: note: in expansion of macro ‘min_t’
185 | min_t(unsigned int, THREAD_SIZE / 8 / sizeof(struct page *), 96U)
| ^~~~~
fs/erofs/zdata.c:847:36: note: in expansion of macro ‘Z_EROFS_VMAP_ONSTACK_PAGES’
847 | struct page *pages_onstack[Z_EROFS_VMAP_ONSTACK_PAGES];
| ^~~~~~~~~~~~~~~~~~~~~~~~~~cc1: all warnings being treated as errors
V1 -> V2:
Use [ Upstream commit <HASH> ] instead of commit <HASH> upstream. like in all other patches.
arch/x86/mm/pgtable.c | 2 +- drivers/edac/sb_edac.c | 4 ++-- drivers/gpu/drm/drm_color_mgmt.c | 2 +- drivers/md/dm-integrity.c | 2 +- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 2 +- fs/erofs/zdata.h | 2 +- net/ipv4/proc.c | 2 +- net/ipv6/proc.c | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-)
arch/x86/mm/pgtable.c +1 -1
@@ -107,7 +107,7 @@ static inline void pgd_list_del(pgd_t *p#define UNSHARED_PTRS_PER_PGD \ (SHARED_KERNEL_PMD ? KERNEL_PGD_BOUNDARY : PTRS_PER_PGD)#define MAX_UNSHARED_PTRS_PER_PGD \ - max_t(size_t, KERNEL_PGD_BOUNDARY, PTRS_PER_PGD) + MAX_T(size_t, KERNEL_PGD_BOUNDARY, PTRS_PER_PGD)static void pgd_set_mm (pgd_t *pgd,struct mm_struct *mm)
drivers/edac/sb_edac.c +2 -2
@@ -109,8 +109,8 @@ static const u32 knl_interleave_list[] = 0x104, 0x10c, 0x114, 0x11c, /* 20-23 */ };#define MAX_INTERLEAVE \ - (max_t(unsigned int, ARRAY_SIZE(sbridge_interleave_list), \ - max_t(unsigned int, ARRAY_SIZE(ibridge_interleave_list), \ + (MAX_T(unsigned int, ARRAY_SIZE(sbridge_interleave_list), \ + MAX_T(unsigned int, ARRAY_SIZE(ibridge_interleave_list), \ ARRAY_SIZE(knl_interleave_list))))struct interleave_pkg {
drivers/gpu/drm/drm_color_mgmt.c +1 -1
@@ -528,7 +528,7 @@ int drm_plane_create_color_properties(st {struct drm_device *dev = plane->dev;struct drm_property *prop; -struct drm_prop_enum_list enum_list[max_t (int,DRM_COLOR_ENCODING_MAX , +struct drm_prop_enum_list enum_list[MAX_T (int,DRM_COLOR_ENCODING_MAX ,DRM_COLOR_RANGE_MAX )];int i, len;
drivers/md/dm-integrity.c +1 -1
@@ -2536,7 +2536,7 @@ static void do_journal_write(struct dm_i unlikely(from_replay) && #endif ic->internal_hash) { -char test_tag[max_t (size_t,HASH_MAX_DIGESTSIZE ,MAX_TAG_SIZE )]; +char test_tag[MAX_T (size_t,HASH_MAX_DIGESTSIZE ,MAX_TAG_SIZE )];integrity_sector_checksum (ic, sec + ((l - j) << ic->sb->log2_sectors_per_block), (char *)access_journal_data (ic, i, l), test_tag);
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +1 -1
@@ -2805,7 +2805,7 @@ static void stmmac_dma_interrupt(structu32 channels_to_check = tx_channel_count > rx_channel_count ? tx_channel_count : rx_channel_count;u32 chan; -int status[max_t (u32,MTL_MAX_TX_QUEUES ,MTL_MAX_RX_QUEUES )]; +int status[MAX_T (u32,MTL_MAX_TX_QUEUES ,MTL_MAX_RX_QUEUES )];/* Make sure we never check beyond our status buffer. */ if (WARN_ON_ONCE (channels_to_check >ARRAY_SIZE (status)))
fs/erofs/zdata.h +1 -1
@@ -182,7 +182,7 @@ static inline void z_erofs_onlinepage_en }#define Z_EROFS_VMAP_ONSTACK_PAGES \ - min_t(unsigned int, THREAD_SIZE / 8 / sizeof(struct page *), 96U) + MIN_T(unsigned int, THREAD_SIZE / 8 / sizeof(struct page *), 96U)#define Z_EROFS_VMAP_GLOBAL_PAGES 2048#endif
net/ipv4/proc.c +1 -1
@@ -43,7 +43,7 @@#include <net/sock.h> #include <net/raw.h> -#define TCPUDP_MIB_MAX max_t(u32, UDP_MIB_MAX, TCP_MIB_MAX) +#define TCPUDP_MIB_MAX MAX_T(u32, UDP_MIB_MAX, TCP_MIB_MAX)/* * Report socket allocation statistics [[email protected]]
net/ipv6/proc.c +1 -1
@@ -27,7 +27,7 @@#include <net/ipv6.h> #define MAX4 (a, b, c, d) \ - max_t(u32, max_t(u32, a, b), max_t(u32, c, d)) + MAX_T(u32, MAX_T(u32, a, b), MAX_T(u32, c, d))#define SNMP_MIB_MAX MAX4(UDP_MIB_MAX, TCP_MIB_MAX, \ IPSTATS_MIB_MAX, ICMP_MIB_MAX)
Greg Kroah-Hartman
maintainerPATCH 247/276 minmax: simplify and clarify min_t()/max_t() implementation
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Linus Torvalds <[email protected]>
[ Upstream commit 017fa3e89187848fd056af757769c9e66ac3e93d ]
This simplifies the min_t() and max_t() macros by no longer making them work in the context of a C constant expression.
That means that you can no longer use them for static initializers or for array sizes in type definitions, but there were only a couple of such uses, and all of them were converted (famous last words) to use MIN_T/MAX_T instead.
---
V1 -> V2:
Use [ Upstream commit <HASH> ] instead of commit <HASH> upstream. like in all other patches.
include/linux/minmax.h | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-)
include/linux/minmax.h +11 -8
@@ -45,17 +45,20 @@#define __cmp (op, x, y) ((x) __cmp_op_##op (y) ? (x) : (y)) -#define __cmp_once (op, x, y, unique_x, unique_y) ({ \ - typeof(x) unique_x = (x); \ - typeof(y) unique_y = (y); \ +#define __cmp_once_unique (op, type, x, y, ux, uy) \ + ({ type ux = (x); type uy = (y); __cmp(op, ux, uy); }) + +#define __cmp_once (op, type, x, y) \ + __cmp_once_unique(op, type, x, y, __UNIQUE_ID(x_), __UNIQUE_ID(y_)) + +#define __careful_cmp_once (op, x, y) ({ \ static_assert(__types_ok(x, y), \ #op "(" #x ", " #y ") signedness error, fix types or consider u" #op "() before " #op "_t()"); \ - __cmp(op, unique_x, unique_y); }) + __cmp_once(op, __auto_type, x, y); })#define __careful_cmp (op, x, y) \ __builtin_choose_expr(__is_constexpr((x) - (y)), \ - __cmp(op, x, y), \ - __cmp_once(op, x, y, __UNIQUE_ID(__x), __UNIQUE_ID(__y))) + __cmp(op, x, y), __careful_cmp_once(op, x, y))#define __clamp (val, lo, hi) \ ((val) >= (hi) ? (hi) : ((val) <= (lo) ? (lo) : (val)))
@@ -158,7 +161,7 @@* @x: first value * @y: second value */ -#define min_t (type, x, y) __careful_cmp(min, (type)(x), (type)(y)) +#define min_t (type, x, y) __cmp_once(min, type, x, y)/** * max_t - return maximum of two values, using the specified type
@@ -166,7 +169,7 @@* @x: first value * @y: second value */ -#define max_t (type, x, y) __careful_cmp(max, (type)(x), (type)(y)) +#define max_t (type, x, y) __cmp_once(max, type, x, y)/* * Do not check the array parameter using __must_be_array().
Greg Kroah-Hartman
maintainerPATCH 248/276 minmax: make generic MIN() and MAX() macros available everywhere
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Linus Torvalds <[email protected]>
[ Upstream commit 1a251f52cfdc417c84411a056bc142cbd77baef4 ]
This just standardizes the use of MIN() and MAX() macros, with the very traditional semantics. The goal is to use these for C constant expressions and for top-level / static initializers, and so be able to simplify the min()/max() macros.
These macro names were used by various kernel code - they are very traditional, after all - and all such users have been fixed up, with a few different approaches:
- trivial duplicated macro definitions have been removed
Note that 'trivial' here means that it's obviously kernel code that already included all the major kernel headers, and thus gets the new generic MIN/MAX macros automatically.
- non-trivial duplicated macro definitions are guarded with #ifndef
This is the "yes, they define their own versions, but no, the include situation is not entirely obvious, and maybe they don't get the generic version automatically" case.
- strange use case #1
A couple of drivers decided that the way they want to describe their versioning is with
#define MAJ 1 #define MIN 2 #define DRV_VERSION __stringify(MAJ) "." __stringify(MIN)
which adds zero value and I just did my Alexander the Great impersonation, and rewrote that pointless Gordian knot as
#define DRV_VERSION "1.2"
instead.
- strange use case #2
A couple of drivers thought that it's a good idea to have a random 'MIN' or 'MAX' define for a value or index into a table, rather than the traditional macro that takes arguments.
These values were re-written as C enum's instead. The new function-line macros only expand when followed by an open parenthesis, and thus don't clash with enum use.
Happily, there weren't really all that many of these cases, and a lot of users already had the pattern of using '#ifndef' guarding (or in one case just using '#undef MIN') before defining their own private version that does the same thing. I left such cases alone.
--- arch/um/drivers/mconsole_user.c | 2 drivers/edac/skx_common.h | 1 drivers/gpu/drm/amd/amdgpu/amdgpu.h | 2 drivers/gpu/drm/amd/display/modules/hdcp/hdcp_ddc.c | 2 drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppevvmath.h | 14 ++++- drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 2 drivers/gpu/drm/radeon/evergreen_cs.c | 2 drivers/hwmon/adt7475.c | 24 +++++----- drivers/media/dvb-frontends/stv0367_priv.h | 3 + drivers/net/fjes/fjes_main.c | 4 - drivers/nfc/pn544/i2c.c | 2 drivers/platform/x86/sony-laptop.c | 1 drivers/scsi/isci/init.c | 6 -- drivers/staging/media/atomisp/pci/hive_isp_css_include/math_support.h | 5 -- include/linux/minmax.h | 2 kernel/trace/preemptirq_delay_test.c | 2 lib/btree.c | 1 lib/decompress_unlzma.c | 2 lib/zstd/zstd_internal.h | 2 mm/zsmalloc.c | 1 tools/testing/selftests/vm/mremap_test.c | 2 21 files changed, 43 insertions(+), 39 deletions(-)
arch/um/drivers/mconsole_user.c +2 -0
@@ -71,7 +71,9 @@ static struct mconsole_command *mconsolereturn NULL ; } +#ifndef MIN #define MIN (a,b) ((a)<(b) ? (a):(b)) +#endif #define STRINGX (x) #x#define STRING (x) STRINGX(x)
drivers/edac/skx_common.h +0 -1
@@ -44,7 +44,6 @@#define I10NM_NUM_CHANNELS MAX(I10NM_NUM_DDR_CHANNELS, I10NM_NUM_HBM_CHANNELS)#define I10NM_NUM_DIMMS MAX(I10NM_NUM_DDR_DIMMS, I10NM_NUM_HBM_DIMMS) -#define MAX (a, b) ((a) > (b) ? (a) : (b))#define NUM_IMC MAX(SKX_NUM_IMC, I10NM_NUM_IMC)#define NUM_CHANNELS MAX(SKX_NUM_CHANNELS, I10NM_NUM_CHANNELS)#define NUM_DIMMS MAX(SKX_NUM_DIMMS, I10NM_NUM_DIMMS)
drivers/gpu/drm/amd/amdgpu/amdgpu.h +2 -0
@@ -1277,7 +1277,9 @@ int emu_soc_asic_init(struct amdgpu_devi#define amdgpu_inc_vram_lost (adev) atomic_inc(&((adev)->vram_lost_counter)); +#ifndef MIN #define MIN (X ,Y ) ((X) < (Y) ? (X) : (Y)) +#endif /* Common functions */ bool amdgpu_device_has_job_running (struct amdgpu_device *adev);
drivers/gpu/drm/amd/display/modules/hdcp/hdcp_ddc.c +2 -0
@@ -25,7 +25,9 @@#include "hdcp.h" +#ifndef MIN #define MIN (a, b) ((a) < (b) ? (a) : (b)) +#endif #define HDCP_I2C_ADDR 0x3a/* 0x74 >> 1*/ #define KSV_READ_SIZE 0xf/* 0x6803b - 0x6802c */ #define HDCP_MAX_AUX_TRANSACTION_SIZE 16
drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppevvmath.h +10 -4
@@ -22,12 +22,18 @@*/ #include <asm/div64.h> -#define SHIFT_AMOUNT 16/* We multiply all original integers with 2^SHIFT_AMOUNT to get the fInt representation */ +enum ppevvmath_constants { +/* We multiply all original integers with 2^SHIFT_AMOUNT to get the fInt representation */ +SHIFT_AMOUNT =16 , -#define PRECISION 5/* Change this value to change the number of decimal places in the final output - 5 is a good default */ +/* Change this value to change the number of decimal places in the final output - 5 is a good default */ +PRECISION =5 , -#define SHIFTED_2 (2 << SHIFT_AMOUNT) -#define MAX (1 << (SHIFT_AMOUNT - 1)) - 1/* 32767 - Might change in the future */ +SHIFTED_2 = (2 <<SHIFT_AMOUNT ), + +/* 32767 - Might change in the future */ +MAX = (1 << (SHIFT_AMOUNT -1 )) -1 , +};/* ------------------------------------------------------------------------------- * NEW TYPE - fINT
drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c +2 -0
@@ -1964,7 +1964,9 @@ static void sienna_cichlid_get_override_ } } +#ifndef MAX #define MAX (a, b) ((a) > (b) ? (a) : (b)) +#endif static int sienna_cichlid_update_pcie_parameters(struct smu_context *smu, uint32_t pcie_gen_cap,
drivers/gpu/drm/radeon/evergreen_cs.c +2 -0
@@ -33,8 +33,10 @@#include "evergreen_reg_safe.h" #include "cayman_reg_safe.h" +#ifndef MIN #define MAX (a,b) (((a)>(b))?(a):(b))#define MIN (a,b) (((a)<(b))?(a):(b)) +#endif #define REG_SAFE_BM_SIZE ARRAY_SIZE(evergreen_reg_safe_bm)
drivers/hwmon/adt7475.c +12 -12
@@ -23,23 +23,23 @@#include <linux/util_macros.h> /* Indexes for the sysfs hooks */ - -#define INPUT 0 -#define MIN 1 -#define MAX 2 -#define CONTROL 3 -#define OFFSET 3 -#define AUTOMIN 4 -#define THERM 5 -#define HYSTERSIS 6 - +enum adt_sysfs_id { +INPUT =0 , +MIN =1 , +MAX =2 , +CONTROL =3 , +OFFSET =3 ,// Dup +AUTOMIN =4 , +THERM =5 , +HYSTERSIS =6 ,/* * These are unique identifiers for the sysfs functions - unlike the * numbers above, these are not also indexes into an array */ +ALARM =9 , +FAULT =10 , +}; -#define ALARM 9 -#define FAULT 10/* 7475 Common Registers */
drivers/media/dvb-frontends/stv0367_priv.h +3 -0
@@ -25,8 +25,11 @@#endif /* MACRO definitions */ +#ifndef MIN #define MAX (X ,Y ) ((X) >= (Y) ? (X) : (Y))#define MIN (X ,Y ) ((X) <= (Y) ? (X) : (Y)) +#endif +#define INRANGE (X ,Y ,Z ) \ ((((X) <= (Y)) && ((Y) <= (Z))) || \ (((Z) <= (Y)) && ((Y) <= (X))) ? 1 : 0)
drivers/net/fjes/fjes_main.c +1 -3
@@ -14,9 +14,7 @@#include "fjes.h" #include "fjes_trace.h" -#define MAJ 1 -#define MIN 2 -#define DRV_VERSION __stringify(MAJ) "." __stringify(MIN) +#define DRV_VERSION "1.2"#define DRV_NAME "fjes"char fjes_driver_name[] =DRV_NAME ;char fjes_driver_version[] =DRV_VERSION ;
drivers/nfc/pn544/i2c.c +0 -2
@@ -126,8 +126,6 @@ struct pn544_i2c_fw_secure_blob {#define PN544_FW_CMD_RESULT_COMMAND_REJECTED 0xE0#define PN544_FW_CMD_RESULT_CHUNK_ERROR 0xE6 -#define MIN (X ,Y ) ((X) < (Y) ? (X) : (Y)) -#define PN544_FW_WRITE_BUFFER_MAX_LEN 0x9f7#define PN544_FW_I2C_MAX_PAYLOAD PN544_HCI_I2C_LLC_MAX_SIZE#define PN544_FW_I2C_WRITE_FRAME_HEADER_LEN 8
drivers/platform/x86/sony-laptop.c +0 -1
@@ -757,7 +757,6 @@ static union acpi_object *__call_snc_metreturn result; } -#define MIN (a, b) (a > b ? b : a)static int sony_nc_buffer_call (acpi_handle handle,char *name,u64 *value,void *buffer,size_t buflen) {
drivers/scsi/isci/init.c +1 -5
@@ -65,11 +65,7 @@#include "task.h" #include "probe_roms.h" -#define MAJ 1 -#define MIN 2 -#define BUILD 0 -#define DRV_VERSION __stringify(MAJ) "." __stringify(MIN) "." \ - __stringify(BUILD) +#define DRV_VERSION "1.2.0"MODULE_VERSION (DRV_VERSION );
drivers/staging/media/atomisp/pci/hive_isp_css_include/math_support.h +0 -5
@@ -31,11 +31,6 @@/* A => B */ #define IMPLIES (a, b) (!(a) || (b)) -/* for preprocessor and array sizing use MIN and MAX -otherwise use min and max */ -#define MAX (a, b) (((a) > (b)) ? (a) : (b)) -#define MIN (a, b) (((a) < (b)) ? (a) : (b)) -#define ROUND_DIV (a, b) (((b) != 0) ? ((a) + ((b) >> 1)) / (b) : 0)#define CEIL_DIV (a, b) (((b) != 0) ? ((a) + (b) - 1) / (b) : 0)#define CEIL_MUL (a, b) (CEIL_DIV(a, b) * (b))
include/linux/minmax.h +2 -0
@@ -277,6 +277,8 @@ static inline bool in_range32(u32 val, u* Use these carefully: no type checking, and uses the arguments * multiple times. Use for obvious constants only. */ +#define MIN (a,b) __cmp(min,a,b) +#define MAX (a,b) __cmp(max,a,b)#define MIN_T (type,a,b) __cmp(min,(type)(a),(type)(b))#define MAX_T (type,a,b) __cmp(max,(type)(a),(type)(b))
kernel/trace/preemptirq_delay_test.c +0 -2
@@ -34,8 +34,6 @@ MODULE_PARM_DESC(cpu_affinity, "Cpu numstatic struct completion done; -#define MIN (x, y) ((x) < (y) ? (x) : (y)) -static void busy_wait (ulong time) {u64 start, end;
lib/btree.c +0 -1
@@ -43,7 +43,6 @@#include <linux/slab.h> #include <linux/module.h> -#define MAX (a, b) ((a) > (b) ? (a) : (b))#define NODESIZE MAX(L1_CACHE_BYTES, 128)struct btree_geo {
lib/decompress_unlzma.c +2 -0
@@ -37,7 +37,9 @@#include <linux/decompress/mm.h> +#ifndef MIN #define MIN (a, b) (((a) < (b)) ? (a) : (b)) +#endif static long long INIT read_int (unsigned char *ptr,int size) {
lib/zstd/zstd_internal.h +0 -2
@@ -36,8 +36,6 @@/*-************************************* * shared macros ***************************************/ -#define MIN (a, b) ((a) < (b) ? (a) : (b)) -#define MAX (a, b) ((a) > (b) ? (a) : (b))#define CHECK_F (f) \ { \ size_t const errcod = f; \
mm/zsmalloc.c +0 -1
@@ -126,7 +126,6 @@#define ISOLATED_BITS 3#define MAGIC_VAL_BITS 8 -#define MAX (a, b) ((a) >= (b) ? (a) : (b))/* ZS_MIN_ALLOC_SIZE must be multiple of ZS_ALIGN */ #define ZS_MIN_ALLOC_SIZE \ MAX(32, (ZS_MAX_PAGES_PER_ZSPAGE << PAGE_SHIFT >> OBJ_INDEX_BITS))
tools/testing/selftests/vm/mremap_test.c +2 -0
@@ -22,7 +22,9 @@#define VALIDATION_DEFAULT_THRESHOLD 4/* 4MB */ #define VALIDATION_NO_THRESHOLD 0/* Verify the entire region */ +#ifndef MIN #define MIN (X ,Y ) ((X) < (Y) ? (X) : (Y)) +#endif struct config {unsigned long long src_alignment;
Greg Kroah-Hartman
maintainerPATCH 249/276 minmax: dont use max() in situations that want a C constant expression
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Linus Torvalds <[email protected]>
[ Upstream commit cb04e8b1d2f24c4c2c92f7b7529031fc35a16fed ]
We only had a couple of array[] declarations, and changing them to just use 'MAX()' instead of 'max()' fixes the issue.
This will allow us to simplify our min/max macros enormously, since they can now unconditionally use temporary variables to avoid using the argument values multiple times.
--- drivers/input/touchscreen/cyttsp4_core.c | 2 +- drivers/irqchip/irq-sun6i-r.c | 2 +- drivers/md/dm-integrity.c | 2 +- fs/btrfs/tree-checker.c | 2 +- lib/vsprintf.c | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-)
drivers/input/touchscreen/cyttsp4_core.c +1 -1
@@ -871,7 +871,7 @@ static void cyttsp4_get_mt_touches(strucstruct cyttsp4_touch tch;int sig;int i, j, t =0 ; -int ids[max (CY_TMA1036_MAX_TCH ,CY_TMA4XX_MAX_TCH )]; +int ids[MAX (CY_TMA1036_MAX_TCH ,CY_TMA4XX_MAX_TCH )];memset (ids,0 , si->si_ofs.tch_abs[CY_TCH_T ].max *sizeof (int ));for (i =0 ; i < num_cur_tch; i++) {
drivers/irqchip/irq-sun6i-r.c +1 -1
@@ -268,7 +268,7 @@ static const struct irq_domain_ops sun6istatic int sun6i_r_intc_suspend (void ) { -u32 buf[BITS_TO_U32 (max (SUN6I_NR_TOP_LEVEL_IRQS ,SUN6I_NR_MUX_BITS ))]; +u32 buf[BITS_TO_U32 (MAX (SUN6I_NR_TOP_LEVEL_IRQS ,SUN6I_NR_MUX_BITS ))];int i;/* Wake IRQs are enabled during system sleep and shutdown. */
drivers/md/dm-integrity.c +1 -1
@@ -1705,7 +1705,7 @@ static void integrity_metadata(struct wostruct bio *bio =dm_bio_from_per_bio_data (dio,sizeof (struct dm_integrity_io ));char *checksums;unsigned extra_space =unlikely (digest_size > ic->tag_size) ? digest_size - ic->tag_size :0 ; -char checksums_onstack[max ((size_t )HASH_MAX_DIGESTSIZE ,MAX_TAG_SIZE )]; +char checksums_onstack[MAX (HASH_MAX_DIGESTSIZE ,MAX_TAG_SIZE )];sector_t sector;unsigned sectors_to_process;
fs/btrfs/tree-checker.c +1 -1
@@ -608,7 +608,7 @@ static int check_dir_item(struct extent_*/ if (key->type ==BTRFS_DIR_ITEM_KEY || key->type ==BTRFS_XATTR_ITEM_KEY ) { -char namebuf[max (BTRFS_NAME_LEN ,XATTR_NAME_MAX )]; +char namebuf[MAX (BTRFS_NAME_LEN ,XATTR_NAME_MAX )];read_extent_buffer (leaf, namebuf, (unsigned long )(di +1 ), name_len);
lib/vsprintf.c +1 -1
@@ -1100,7 +1100,7 @@ char *resource_string(char *buf, char *e#define FLAG_BUF_SIZE (2 * sizeof(res->flags))#define DECODED_BUF_SIZE sizeof("[mem - 64bit pref window disabled]")#define RAW_BUF_SIZE sizeof("[mem - flags 0x]") -char sym[max (2 *RSRC_BUF_SIZE +DECODED_BUF_SIZE , +char sym[MAX (2 *RSRC_BUF_SIZE +DECODED_BUF_SIZE ,2 *RSRC_BUF_SIZE +FLAG_BUF_SIZE +RAW_BUF_SIZE )];char *p = sym, *pend = sym +sizeof (sym);
Greg Kroah-Hartman
maintainerPATCH 250/276 minmax: simplify min()/max()/clamp() implementation
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Linus Torvalds <[email protected]>
[ Upstream commit dc1c8034e31b14a2e5e212104ec508aec44ce1b9 ]
Now that we no longer have any C constant expression contexts (ie array size declarations or static initializers) that use min() or max(), we can simpify the implementation by not having to worry about the result staying as a C constant expression.
So now we can unconditionally just use temporary variables of the right type, and get rid of the excessive expansion that used to come from the use of
__builtin_choose_expr(__is_constexpr(...), ..
to pick the specialized code for constant expressions.
Another expansion simplification is to pass the temporary variables (in addition to the original expression) to our __types_ok() macro. That may superficially look like it complicates the macro, but when we only want the type of the expression, expanding the temporary variable names is much simpler and smaller than expanding the potentially complicated original expression.
As a result, on my machine, doing a
$ time make drivers/staging/media/atomisp/pci/isp/kernels/ynr/ynr_1.0/ia_css_ynr.host.i
goes from
real 0m16.621s user 0m15.360s sys 0m1.221s
to
real 0m2.532s user 0m2.091s sys 0m0.452s
because the token expansion goes down dramatically.
In particular, the longest line expansion (which was line 71 of that 'ia_css_ynr.host.c' file) shrinks from 23,338kB (yes, 23MB for one single line) to "just" 1,444kB (now "only" 1.4MB).
And yes, that line is still the line from hell, because it's doing multiple levels of "min()/max()" expansion thanks to some of them being hidden inside the uDIGIT_FITTING() macro.
Lorenzo has a nice cleanup patch that makes that driver use inline functions instead of macros for sDIGIT_FITTING() and uDIGIT_FITTING(), which will fix that line once and for all, but the 16-fold reduction in this case does show why we need to simplify these helpers.
--- include/linux/minmax.h | 43 ++++++++++++++++++++----------------------- 1 file changed, 20 insertions(+), 23 deletions(-)
include/linux/minmax.h +20 -23
@@ -35,10 +35,10 @@#define __is_noneg_int (x) \ (__builtin_choose_expr(__is_constexpr(x) && __is_signed(x), x, -1) >= 0) -#define __types_ok (x, y) \ - (__is_signed(x) == __is_signed(y) || \ - __is_signed((x) + 0) == __is_signed((y) + 0) || \ - __is_noneg_int(x) || __is_noneg_int(y)) +#define __types_ok (x, y, ux, uy) \ + (__is_signed(ux) == __is_signed(uy) || \ + __is_signed((ux) + 0) == __is_signed((uy) + 0) || \ + __is_noneg_int(x) || __is_noneg_int(y))#define __cmp_op_min <#define __cmp_op_max >
@@ -51,34 +51,31 @@#define __cmp_once (op, type, x, y) \ __cmp_once_unique(op, type, x, y, __UNIQUE_ID(x_), __UNIQUE_ID(y_)) -#define __careful_cmp_once (op, x, y) ({ \ - static_assert(__types_ok(x, y), \ +#define __careful_cmp_once (op, x, y, ux, uy) ({ \ + __auto_type ux = (x); __auto_type uy = (y); \ + static_assert(__types_ok(x, y, ux, uy), \ #op "(" #x ", " #y ") signedness error, fix types or consider u" #op "() before " #op "_t()"); \ - __cmp_once(op, __auto_type, x, y); }) + __cmp(op, ux, uy); }) -#define __careful_cmp (op, x, y) \ - __builtin_choose_expr(__is_constexpr((x) - (y)), \ - __cmp(op, x, y), __careful_cmp_once(op, x, y)) +#define __careful_cmp (op, x, y) \ + __careful_cmp_once(op, x, y, __UNIQUE_ID(x_), __UNIQUE_ID(y_))#define __clamp (val, lo, hi) \ ((val) >= (hi) ? (hi) : ((val) <= (lo) ? (lo) : (val))) -#define __clamp_once (val, lo, hi, unique_val, unique_lo, unique_hi) ({ \ - typeof(val) unique_val = (val); \ - typeof(lo) unique_lo = (lo); \ - typeof(hi) unique_hi = (hi); \ +#define __clamp_once (val, lo, hi, uval, ulo, uhi) ({ \ + __auto_type uval = (val); \ + __auto_type ulo = (lo); \ + __auto_type uhi = (hi); \ static_assert(__builtin_choose_expr(__is_constexpr((lo) > (hi)), \ (lo) <= (hi), true), \ "clamp() low limit " #lo " greater than high limit " #hi); \ - static_assert(__types_ok(val, lo), "clamp() 'lo' signedness error"); \ - static_assert(__types_ok(val, hi), "clamp() 'hi' signedness error"); \ - __clamp(unique_val, unique_lo, unique_hi); }) - -#define __careful_clamp (val, lo, hi) ({ \ - __builtin_choose_expr(__is_constexpr((val) - (lo) + (hi)), \ - __clamp(val, lo, hi), \ - __clamp_once(val, lo, hi, __UNIQUE_ID(__val), \ - __UNIQUE_ID(__lo), __UNIQUE_ID(__hi))); }) + static_assert(__types_ok(uval, lo, uval, ulo), "clamp() 'lo' signedness error"); \ + static_assert(__types_ok(uval, hi, uval, uhi), "clamp() 'hi' signedness error"); \ + __clamp(uval, ulo, uhi); }) + +#define __careful_clamp (val, lo, hi) \ + __clamp_once(val, lo, hi, __UNIQUE_ID(v_), __UNIQUE_ID(l_), __UNIQUE_ID(h_))/** * min - return minimum of two values of the same or compatible types
Greg Kroah-Hartman
maintainerPATCH 251/276 minmax: improve macro expansion and type checking
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Linus Torvalds <[email protected]>
[ Upstream commit 22f5468731491e53356ba7c028f0fdea20b18e2c ]
This clarifies the rules for min()/max()/clamp() type checking and makes them a much more efficient macro expansion.
In particular, we now look at the type and range of the inputs to see whether they work together, generating a mask of acceptable comparisons, and then just verifying that the inputs have a shared case:
- an expression with a signed type can be used for
(1) signed comparisons
(2) unsigned comparisons if it is statically known to have a non-negative value
- an expression with an unsigned type can be used for
(3) unsigned comparison
(4) signed comparisons if the type is smaller than 'int' and thus the C integer promotion rules will make it signed anyway
Here rule (1) and (3) are obvious, and rule (2) is important in order to allow obvious trivial constants to be used together with unsigned values.
Rule (4) is not necessarily a good idea, but matches what we used to do, and we have extant cases of this situation in the kernel. Notably with bcachefs having an expression like
min(bch2_bucket_sectors_dirty(a), ca->mi.bucket_size)
where bch2_bucket_sectors_dirty() returns an 's64', and 'ca->mi.bucket_size' is of type 'u16'.
Technically that bcachefs comparison is clearly sensible on a C type level, because the 'u16' will go through the normal C integer promotion, and become 'int', and then we're comparing two signed values and everything looks sane.
However, it's not entirely clear that a 'min(s64,u16)' operation makes a lot of conceptual sense, and it's possible that we will remove rule (4). After all, the _reason_ we have these complicated type checks is exactly that the C type promotion rules are not very intuitive.
But at least for now the rule is in place for backwards compatibility.
Also note that rule (2) existed before, but is hugely relaxed by this commit. It used to be true only for the simplest compile-time non-negative integer constants. The new macro model will allow cases where the compiler can trivially see that an expression is non-negative even if it isn't necessarily a constant.
For example, the amdgpu driver does
min_t(size_t, sizeof(fru_info->serial), pia[addr] & 0x3F));
because our old 'min()' macro would see that 'pia[addr] & 0x3F' is of type 'int' and clearly not a C constant expression, so doing a 'min()' with a 'size_t' is a signedness violation.
Our new 'min()' macro still sees that 'pia[addr] & 0x3F' is of type 'int', but is smart enough to also see that it is clearly non-negative, and thus would allow that case without any complaints.
--- include/linux/compiler.h | 9 +++++ include/linux/minmax.h | 78 ++++++++++++++++++++++++++++++++++++----------- 2 files changed, 70 insertions(+), 17 deletions(-)
include/linux/compiler.h +9 -0
@@ -259,6 +259,15 @@ static inline void *offset_to_ptr(const#define is_signed_type (type) (((type)(-1)) < (__force type)1)/* +* Useful shorthand for "is this condition known at compile-time?" +* +* Note that the condition may involve non-constant values, +* but the compiler may know enough about the details of the +* values to determine that the condition is statically true. +*/ +#define statically_true (x) (__builtin_constant_p(x) && (x)) + +/* * This is needed in functions which generate the stack canary, see * arch/x86/kernel/smpboot.c::start_secondary() for an example. */
include/linux/minmax.h +61 -17
96 lines not on this page · raw message
Greg Kroah-Hartman
maintainerPATCH 252/276 minmax: fix up min3() and max3() too
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Linus Torvalds <[email protected]>
[ Upstream commit 21b136cc63d2a9ddd60d4699552b69c214b32964 ]
David Laight pointed out that we should deal with the min3() and max3() mess too, which still does excessive expansion.
And our current macros are actually rather broken.
In particular, the macros did this:
#define min3(x, y, z) min((typeof(x))min(x, y), z) #define max3(x, y, z) max((typeof(x))max(x, y), z)
and that not only is a nested expansion of possibly very complex arguments with all that involves, the typing with that "typeof()" cast is completely wrong.
For example, imagine what happens in max3() if 'x' happens to be a 'unsigned char', but 'y' and 'z' are 'unsigned long'. The types are compatible, and there's no warning - but the result is just random garbage.
No, I don't think we've ever hit that issue in practice, but since we now have sane infrastructure for doing this right, let's just use it. It fixes any excessive expansion, and also avoids these kinds of broken type issues.
--- include/linux/minmax.h | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)
include/linux/minmax.h +10 -2
@@ -152,13 +152,20 @@#define umax (x, y) \ __careful_cmp(max, (x) + 0u + 0ul + 0ull, (y) + 0u + 0ul + 0ull) +#define __careful_op3 (op, x, y, z, ux, uy, uz) ({ \ + __auto_type ux = (x); __auto_type uy = (y);__auto_type uz = (z);\ + BUILD_BUG_ON_MSG(!__types_ok3(x,y,z,ux,uy,uz), \ + #op"3("#x", "#y", "#z") signedness error"); \ + __cmp(op, ux, __cmp(op, uy, uz)); }) +/** * min3 - return minimum of three values * @x: first value * @y: second value * @z: third value */ -#define min3 (x, y, z) min((typeof(x))min(x, y), z) +#define min3 (x, y, z) \ + __careful_op3(min, x, y, z, __UNIQUE_ID(x_), __UNIQUE_ID(y_), __UNIQUE_ID(z_))/** * max3 - return maximum of three values
@@ -166,7 +173,8 @@* @y: second value * @z: third value */ -#define max3 (x, y, z) max((typeof(x))max(x, y), z) +#define max3 (x, y, z) \ + __careful_op3(max, x, y, z, __UNIQUE_ID(x_), __UNIQUE_ID(y_), __UNIQUE_ID(z_))/** * min_not_zero - return the minimum that is _not_ zero, unless both are zero
Greg Kroah-Hartman
maintainerPATCH 253/276 minmax.h: add whitespace around operators and after commas
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Laight <[email protected]>
[ Upstream commit 71ee9b16251ea4bf7c1fe222517c82bdb3220acc ]
Patch series "minmax.h: Cleanups and minor optimisations".
Some tidyups and minor changes to minmax.h.
This patch (of 7):
--- include/linux/minmax.h | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-)
include/linux/minmax.h +17 -17
@@ -51,10 +51,10 @@* only need to be careful to not cause warnings for * pointer use. */ -#define __signed_type_use (x,ux) (2+__is_nonneg(x,ux)) -#define __unsigned_type_use (x,ux) (1+2*(sizeof(ux)<4)) -#define __sign_use (x,ux) (is_signed_type(typeof(ux))? \ - __signed_type_use(x,ux):__unsigned_type_use(x,ux)) +#define __signed_type_use (x, ux) (2 + __is_nonneg(x, ux)) +#define __unsigned_type_use (x, ux) (1 + 2 * (sizeof(ux) < 4)) +#define __sign_use (x, ux) (is_signed_type(typeof(ux)) ? \ + __signed_type_use(x, ux) : __unsigned_type_use(x, ux))/* * To avoid warnings about casting pointers to integers
@@ -74,15 +74,15 @@#ifdef CONFIG_64BIT #define __signed_type (ux) long#else -#define __signed_type (ux) typeof(__builtin_choose_expr(sizeof(ux)>4,1LL,1L)) +#define __signed_type (ux) typeof(__builtin_choose_expr(sizeof(ux) > 4, 1LL, 1L))#endif -#define __is_nonneg (x,ux) statically_true((__signed_type(ux))(x)>=0) +#define __is_nonneg (x, ux) statically_true((__signed_type(ux))(x) >= 0) -#define __types_ok (x,y,ux,uy) \ - (__sign_use(x,ux) & __sign_use(y,uy)) +#define __types_ok (x, y, ux, uy) \ + (__sign_use(x, ux) & __sign_use(y, uy)) -#define __types_ok3 (x,y,z,ux,uy,uz) \ - (__sign_use(x,ux) & __sign_use(y,uy) & __sign_use(z,uz)) +#define __types_ok3 (x, y, z, ux, uy, uz) \ + (__sign_use(x, ux) & __sign_use(y, uy) & __sign_use(z, uz))#define __cmp_op_min <#define __cmp_op_max >
@@ -97,7 +97,7 @@#define __careful_cmp_once (op, x, y, ux, uy) ({ \ __auto_type ux = (x); __auto_type uy = (y); \ - BUILD_BUG_ON_MSG(!__types_ok(x,y,ux,uy), \ + BUILD_BUG_ON_MSG(!__types_ok(x, y, ux, uy), \ #op"("#x", "#y") signedness error"); \ __cmp(op, ux, uy); })
@@ -114,7 +114,7 @@ static_assert(__builtin_choose_expr(__is_constexpr((lo) > (hi)), \ (lo) <= (hi), true), \ "clamp() low limit " #lo " greater than high limit " #hi); \ - BUILD_BUG_ON_MSG(!__types_ok3(val,lo,hi,uval,ulo,uhi), \ + BUILD_BUG_ON_MSG(!__types_ok3(val, lo, hi, uval, ulo, uhi), \ "clamp("#val", "#lo", "#hi") signedness error"); \ __clamp(uval, ulo, uhi); })
@@ -154,7 +154,7 @@#define __careful_op3 (op, x, y, z, ux, uy, uz) ({ \ __auto_type ux = (x); __auto_type uy = (y);__auto_type uz = (z);\ - BUILD_BUG_ON_MSG(!__types_ok3(x,y,z,ux,uy,uz), \ + BUILD_BUG_ON_MSG(!__types_ok3(x, y, z, ux, uy, uz), \ #op"3("#x", "#y", "#z") signedness error"); \ __cmp(op, ux, __cmp(op, uy, uz)); })
@@ -326,9 +326,9 @@ static inline bool in_range32(u32 val, u* Use these carefully: no type checking, and uses the arguments * multiple times. Use for obvious constants only. */ -#define MIN (a,b) __cmp(min,a,b) -#define MAX (a,b) __cmp(max,a,b) -#define MIN_T (type,a,b) __cmp(min,(type)(a),(type)(b)) -#define MAX_T (type,a,b) __cmp(max,(type)(a),(type)(b)) +#define MIN (a, b) __cmp(min, a, b) +#define MAX (a, b) __cmp(max, a, b) +#define MIN_T (type, a, b) __cmp(min, (type)(a), (type)(b)) +#define MAX_T (type, a, b) __cmp(max, (type)(a), (type)(b))#endif /* _LINUX_MINMAX_H */
Greg Kroah-Hartman
maintainerPATCH 254/276 minmax.h: update some comments
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Laight <[email protected]>
[ Upstream commit 10666e99204818ef45c702469488353b5bb09ec7 ]
- Change three to several.
- Remove the comment about retaining constant expressions, no longer true.
- Realign to nearer 80 columns and break on major punctiation.
- Add a leading comment to the block before __signed_type() and __is_nonneg() Otherwise the block explaining the cast is a bit 'floating'. Reword the rest of that comment to improve readability.
--- include/linux/minmax.h | 61 ++++++++++++++++++++++--------------------------- 1 file changed, 28 insertions(+), 33 deletions(-)
include/linux/minmax.h +28 -33
@@ -8,13 +8,10 @@#include <linux/types.h> /* -* min()/max()/clamp() macros must accomplish three things: +* min()/max()/clamp() macros must accomplish several things: * * - Avoid multiple evaluations of the arguments (so side-effects like * "x++" happen only once) when non-constant. -* - Retain result as a constant expressions when called with only -* constant expressions (to avoid tripping VLA warnings in stack -* allocation usage). * - Perform signed v unsigned type-checking (to generate compile * errors instead of nasty runtime surprises). * - Unsigned char/short are always promoted to signed int and can be
@@ -31,25 +28,23 @@* bit #0 set if ok for unsigned comparisons * bit #1 set if ok for signed comparisons * -* In particular, statically non-negative signed integer -* expressions are ok for both. +* In particular, statically non-negative signed integer expressions +* are ok for both. * -* NOTE! Unsigned types smaller than 'int' are implicitly -* converted to 'int' in expressions, and are accepted for -* signed conversions for now. This is debatable. -* -* Note that 'x' is the original expression, and 'ux' is -* the unique variable that contains the value. -* -* We use 'ux' for pure type checking, and 'x' for when -* we need to look at the value (but without evaluating -* it for side effects! Careful to only ever evaluate it -* with sizeof() or __builtin_constant_p() etc). -* -* Pointers end up being checked by the normal C type -* rules at the actual comparison, and these expressions -* only need to be careful to not cause warnings for -* pointer use. +* NOTE! Unsigned types smaller than 'int' are implicitly converted to 'int' +* in expressions, and are accepted for signed conversions for now. +* This is debatable. +* +* Note that 'x' is the original expression, and 'ux' is the unique variable +* that contains the value. +* +* We use 'ux' for pure type checking, and 'x' for when we need to look at the +* value (but without evaluating it for side effects! +* Careful to only ever evaluate it with sizeof() or __builtin_constant_p() etc). +* +* Pointers end up being checked by the normal C type rules at the actual +* comparison, and these expressions only need to be careful to not cause +* warnings for pointer use. */ #define __signed_type_use (x, ux) (2 + __is_nonneg(x, ux))#define __unsigned_type_use (x, ux) (1 + 2 * (sizeof(ux) < 4))
@@ -57,19 +52,19 @@ __signed_type_use(x, ux) : __unsigned_type_use(x, ux))/* -* To avoid warnings about casting pointers to integers -* of different sizes, we need that special sign type. +* Check whether a signed value is always non-negative. * -* On 64-bit we can just always use 'long', since any -* integer or pointer type can just be cast to that. +* A cast is needed to avoid any warnings from values that aren't signed +* integer types (in which case the result doesn't matter). * -* This does not work for 128-bit signed integers since -* the cast would truncate them, but we do not use s128 -* types in the kernel (we do use 'u128', but they will -* be handled by the !is_signed_type() case). -* -* NOTE! The cast is there only to avoid any warnings -* from when values that aren't signed integer types. +* On 64-bit any integer or pointer type can safely be cast to 'long'. +* But on 32-bit we need to avoid warnings about casting pointers to integers +* of different sizes without truncating 64-bit values so 'long' or 'long long' +* must be used depending on the size of the value. +* +* This does not work for 128-bit signed integers since the cast would truncate +* them, but we do not use s128 types in the kernel (we do use 'u128', +* but they are handled by the !is_signed_type() case). */ #ifdef CONFIG_64BIT #define __signed_type (ux) long
Greg Kroah-Hartman
maintainerPATCH 255/276 minmax.h: reduce the #define expansion of min(), max() and clamp()
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Laight <[email protected]>
[ Upstream commit b280bb27a9f7c91ddab730e1ad91a9c18a051f41 ]
Since the test for signed values being non-negative only relies on __builtion_constant_p() (not is_constexpr()) it can use the 'ux' variable instead of the caller supplied expression. This means that the #define parameters are only expanded twice. Once in the code and once quoted in the error message.
--- include/linux/minmax.h | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-)
include/linux/minmax.h +12 -12
@@ -46,10 +46,10 @@* comparison, and these expressions only need to be careful to not cause * warnings for pointer use. */ -#define __signed_type_use (x, ux) (2 + __is_nonneg(x, ux)) -#define __unsigned_type_use (x, ux) (1 + 2 * (sizeof(ux) < 4)) -#define __sign_use (x, ux) (is_signed_type(typeof(ux)) ? \ - __signed_type_use(x, ux) : __unsigned_type_use(x, ux)) +#define __signed_type_use (ux) (2 + __is_nonneg(ux)) +#define __unsigned_type_use (ux) (1 + 2 * (sizeof(ux) < 4)) +#define __sign_use (ux) (is_signed_type(typeof(ux)) ? \ + __signed_type_use(ux) : __unsigned_type_use(ux))/* * Check whether a signed value is always non-negative.
@@ -71,13 +71,13 @@#else #define __signed_type (ux) typeof(__builtin_choose_expr(sizeof(ux) > 4, 1LL, 1L))#endif -#define __is_nonneg (x, ux) statically_true((__signed_type(ux))(x) >= 0) +#define __is_nonneg (ux) statically_true((__signed_type(ux))(ux) >= 0) -#define __types_ok (x, y, ux, uy) \ - (__sign_use(x, ux) & __sign_use(y, uy)) +#define __types_ok (ux, uy) \ + (__sign_use(ux) & __sign_use(uy)) -#define __types_ok3 (x, y, z, ux, uy, uz) \ - (__sign_use(x, ux) & __sign_use(y, uy) & __sign_use(z, uz)) +#define __types_ok3 (ux, uy, uz) \ + (__sign_use(ux) & __sign_use(uy) & __sign_use(uz))#define __cmp_op_min <#define __cmp_op_max >
@@ -92,7 +92,7 @@#define __careful_cmp_once (op, x, y, ux, uy) ({ \ __auto_type ux = (x); __auto_type uy = (y); \ - BUILD_BUG_ON_MSG(!__types_ok(x, y, ux, uy), \ + BUILD_BUG_ON_MSG(!__types_ok(ux, uy), \ #op"("#x", "#y") signedness error"); \ __cmp(op, ux, uy); })
@@ -109,7 +109,7 @@ static_assert(__builtin_choose_expr(__is_constexpr((lo) > (hi)), \ (lo) <= (hi), true), \ "clamp() low limit " #lo " greater than high limit " #hi); \ - BUILD_BUG_ON_MSG(!__types_ok3(val, lo, hi, uval, ulo, uhi), \ + BUILD_BUG_ON_MSG(!__types_ok3(uval, ulo, uhi), \ "clamp("#val", "#lo", "#hi") signedness error"); \ __clamp(uval, ulo, uhi); })
@@ -149,7 +149,7 @@#define __careful_op3 (op, x, y, z, ux, uy, uz) ({ \ __auto_type ux = (x); __auto_type uy = (y);__auto_type uz = (z);\ - BUILD_BUG_ON_MSG(!__types_ok3(x, y, z, ux, uy, uz), \ + BUILD_BUG_ON_MSG(!__types_ok3(ux, uy, uz), \ #op"3("#x", "#y", "#z") signedness error"); \ __cmp(op, ux, __cmp(op, uy, uz)); })
Greg Kroah-Hartman
maintainerPATCH 256/276 minmax.h: use BUILD_BUG_ON_MSG() for the lo < hi test in clamp()
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Laight <[email protected]>
[ Upstream commit a5743f32baec4728711bbc01d6ac2b33d4c67040 ]
Use BUILD_BUG_ON_MSG(statically_true(ulo > uhi), ...) for the sanity check of the bounds in clamp(). Gives better error coverage and one less expansion of the arguments.
--- include/linux/minmax.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
include/linux/minmax.h +1 -2
@@ -106,8 +106,7 @@__auto_type uval = (val); \__auto_type ulo = (lo); \__auto_type uhi = (hi); \ - static_assert(__builtin_choose_expr(__is_constexpr((lo) > (hi)), \ - (lo) <= (hi), true), \ + BUILD_BUG_ON_MSG(statically_true(ulo > uhi), \ "clamp() low limit " #lo " greater than high limit " #hi); \ BUILD_BUG_ON_MSG(!__types_ok3(uval, ulo, uhi), \ "clamp("#val", "#lo", "#hi") signedness error"); \
Greg Kroah-Hartman
maintainerPATCH 257/276 minmax.h: move all the clamp() definitions after the min/max() ones
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Laight <[email protected]>
[ Upstream commit c3939872ee4a6b8bdcd0e813c66823b31e6e26f7 ]
At some point the definitions for clamp() got added in the middle of the ones for min() and max(). Re-order the definitions so they are more sensibly grouped.
--- include/linux/minmax.h | 109 ++++++++++++++++++++++--------------------------- 1 file changed, 51 insertions(+), 58 deletions(-)
include/linux/minmax.h +51 -58
@@ -99,22 +99,6 @@#define __careful_cmp (op, x, y) \ __careful_cmp_once(op, x, y, __UNIQUE_ID(x_), __UNIQUE_ID(y_)) -#define __clamp (val, lo, hi) \ - ((val) >= (hi) ? (hi) : ((val) <= (lo) ? (lo) : (val))) - -#define __clamp_once (val, lo, hi, uval, ulo, uhi) ({ \ - __auto_type uval = (val); \ - __auto_type ulo = (lo); \ - __auto_type uhi = (hi); \ - BUILD_BUG_ON_MSG(statically_true(ulo > uhi), \ - "clamp() low limit " #lo " greater than high limit " #hi); \ - BUILD_BUG_ON_MSG(!__types_ok3(uval, ulo, uhi), \ - "clamp("#val", "#lo", "#hi") signedness error"); \ - __clamp(uval, ulo, uhi); }) - -#define __careful_clamp (val, lo, hi) \ - __clamp_once(val, lo, hi, __UNIQUE_ID(v_), __UNIQUE_ID(l_), __UNIQUE_ID(h_)) -/** * min - return minimum of two values of the same or compatible types * @x: first value
@@ -171,6 +155,22 @@__careful_op3 (max, x, y, z,__UNIQUE_ID (x_),__UNIQUE_ID (y_),__UNIQUE_ID (z_))/** +* min_t - return minimum of two values, using the specified type +* @type: data type to use +* @x: first value +* @y: second value + */ +#define min_t (type, x, y) __cmp_once(min, type, x, y) + +/** +* max_t - return maximum of two values, using the specified type +* @type: data type to use +* @x: first value +* @y: second value +*/ +#define max_t (type, x, y) __cmp_once(max, type, x, y) + +/** * min_not_zero - return the minimum that is _not_ zero, unless both are zero * @x: value1 * @y: value2
@@ -180,6 +180,22 @@typeof (y) __y = (y); \ __x == 0 ? __y : ((__y == 0) ? __x : min(__x, __y)); }) +#define __clamp (val, lo, hi) \ + ((val) >= (hi) ? (hi) : ((val) <= (lo) ? (lo) : (val))) + +#define __clamp_once (val, lo, hi, uval, ulo, uhi) ({ \ + __auto_type uval = (val); \ + __auto_type ulo = (lo); \ + __auto_type uhi = (hi); \ + BUILD_BUG_ON_MSG(statically_true(ulo > uhi), \ + "clamp() low limit " #lo " greater than high limit " #hi); \ + BUILD_BUG_ON_MSG(!__types_ok3(uval, ulo, uhi), \ + "clamp("#val", "#lo", "#hi") signedness error"); \ + __clamp(uval, ulo, uhi); }) + +#define __careful_clamp (val, lo, hi) \ + __clamp_once(val, lo, hi, __UNIQUE_ID(v_), __UNIQUE_ID(l_), __UNIQUE_ID(h_)) +/** * clamp - return a value clamped to a given range with strict typechecking * @val: current value
@@ -191,28 +207,30 @@*/ #define clamp (val, lo, hi) __careful_clamp(val, lo, hi) -/* -* ..and if you can't take the strict -* types, you can specify one yourself. -* -* Or not use min/max/clamp at all, of course. -*/ -/** -* min_t - return minimum of two values, using the specified type -* @type: data type to use -* @x: first value -* @y: second value +* clamp_t - return a value clamped to a given range using a given type +* @type: the type of variable to use +* @val: current value +* @lo: minimum allowable value +* @hi: maximum allowable value +* +* This macro does no typechecking and uses temporary variables of type +* @type to make all the comparisons. */ -#define min_t (type, x, y) __cmp_once(min, type, x, y) +#define clamp_t (type, val, lo, hi) __careful_clamp((type)(val), (type)(lo), (type)(hi))/** -* max_t - return maximum of two values, using the specified type -* @type: data type to use -* @x: first value -* @y: second value +* clamp_val - return a value clamped to a given range using val's type +* @val: current value +* @lo: minimum allowable value +* @hi: maximum allowable value +* +* This macro does no typechecking and uses temporary variables of whatever +* type the input argument @val is. This is useful when @val is an unsigned +* type and @lo and @hi are literals that will otherwise be assigned a signed +* integer type. */ -#define max_t (type, x, y) __cmp_once(max, type, x, y) +#define clamp_val (val, lo, hi) clamp_t(typeof(val), val, lo, hi)/* * Do not check the array parameter using __must_be_array().
@@ -257,31 +275,6 @@*/ #define max_array (array, len) __minmax_array(max, array, len) -/** -* clamp_t - return a value clamped to a given range using a given type -* @type: the type of variable to use -* @val: current value -* @lo: minimum allowable value -* @hi: maximum allowable value -* -* This macro does no typechecking and uses temporary variables of type -* @type to make all the comparisons. -*/ -#define clamp_t (type, val, lo, hi) __careful_clamp((type)(val), (type)(lo), (type)(hi)) - -/** -* clamp_val - return a value clamped to a given range using val's type -* @val: current value -* @lo: minimum allowable value -* @hi: maximum allowable value -* -* This macro does no typechecking and uses temporary variables of whatever -* type the input argument @val is. This is useful when @val is an unsigned -* type and @lo and @hi are literals that will otherwise be assigned a signed -* integer type. -*/ -#define clamp_val (val, lo, hi) clamp_t(typeof(val), val, lo, hi) -static inline bool in_range64 (u64 val,u64 start,u64 len) {return (val - start) < len;
Greg Kroah-Hartman
maintainerPATCH 258/276 minmax.h: simplify the variants of clamp()
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Laight <[email protected]>
[ Upstream commit 495bba17cdf95e9703af1b8ef773c55ef0dfe703 ]
Always pass a 'type' through to __clamp_once(), pass '__auto_type' from clamp() itself.
The expansion of __types_ok3() is reasonable so it isn't worth the added complexity of avoiding it when a fixed type is used for all three values.
--- include/linux/minmax.h | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-)
include/linux/minmax.h +12 -12
@@ -183,29 +183,29 @@#define __clamp (val, lo, hi) \ ((val) >= (hi) ? (hi) : ((val) <= (lo) ? (lo) : (val))) -#define __clamp_once (val, lo, hi, uval, ulo, uhi) ({ \ - __auto_type uval = (val); \ - __auto_type ulo = (lo); \ - __auto_type uhi = (hi); \ +#define __clamp_once (type, val, lo, hi, uval, ulo, uhi) ({ \ + type uval = (val); \ + type ulo = (lo); \ + type uhi = (hi); \ BUILD_BUG_ON_MSG(statically_true(ulo > uhi), \ "clamp() low limit " #lo " greater than high limit " #hi); \ BUILD_BUG_ON_MSG(!__types_ok3(uval, ulo, uhi), \ "clamp("#val", "#lo", "#hi") signedness error"); \ __clamp(uval, ulo, uhi); }) -#define __careful_clamp (val, lo, hi) \ - __clamp_once(val, lo, hi, __UNIQUE_ID(v_), __UNIQUE_ID(l_), __UNIQUE_ID(h_)) +#define __careful_clamp (type, val, lo, hi) \ + __clamp_once(type, val, lo, hi, __UNIQUE_ID(v_), __UNIQUE_ID(l_), __UNIQUE_ID(h_))/** -* clamp - return a value clamped to a given range with strict typechecking +* clamp - return a value clamped to a given range with typechecking * @val: current value * @lo: lowest allowable value * @hi: highest allowable value * -* This macro does strict typechecking of @lo/@hi to make sure they are of the -* same type as @val. See the unnecessary pointer comparisons. +* This macro checks @val/@lo/@hi to make sure they have compatible +* signedness. */ -#define clamp (val, lo, hi) __careful_clamp(val, lo, hi) +#define clamp (val, lo, hi) __careful_clamp(__auto_type, val, lo, hi)/** * clamp_t - return a value clamped to a given range using a given type
@@ -217,7 +217,7 @@* This macro does no typechecking and uses temporary variables of type * @type to make all the comparisons. */ -#define clamp_t (type, val, lo, hi) __careful_clamp((type)(val), (type)(lo), (type)(hi)) +#define clamp_t (type, val, lo, hi) __careful_clamp(type, val, lo, hi)/** * clamp_val - return a value clamped to a given range using val's type
@@ -230,7 +230,7 @@* type and @lo and @hi are literals that will otherwise be assigned a signed * integer type. */ -#define clamp_val (val, lo, hi) clamp_t(typeof(val), val, lo, hi) +#define clamp_val (val, lo, hi) __careful_clamp(typeof(val), val, lo, hi)/* * Do not check the array parameter using __must_be_array().
Greg Kroah-Hartman
maintainerPATCH 259/276 minmax.h: remove some #defines that are only expanded once
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Laight <[email protected]>
[ Upstream commit 2b97aaf74ed534fb838d09867d09a3ca5d795208 ]
The bodies of __signed_type_use() and __unsigned_type_use() are much the same size as their names - so put the bodies in the only line that expands them.
Similarly __signed_type() is defined separately for 64bit and then used exactly once just below.
Change the test for __signed_type from CONFIG_64BIT to one based on gcc defined macros so that the code is valid if it gets used outside of a kernel build.
--- include/linux/minmax.h | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-)
include/linux/minmax.h +6 -8
@@ -46,10 +46,8 @@* comparison, and these expressions only need to be careful to not cause * warnings for pointer use. */ -#define __signed_type_use (ux) (2 + __is_nonneg(ux)) -#define __unsigned_type_use (ux) (1 + 2 * (sizeof(ux) < 4))#define __sign_use (ux) (is_signed_type(typeof(ux)) ? \ - __signed_type_use(ux) : __unsigned_type_use(ux)) + (2 + __is_nonneg(ux)) : (1 + 2 * (sizeof(ux) < 4)))/* * Check whether a signed value is always non-negative.
@@ -57,7 +55,7 @@* A cast is needed to avoid any warnings from values that aren't signed * integer types (in which case the result doesn't matter). * -* On 64-bit any integer or pointer type can safely be cast to 'long'. +* On 64-bit any integer or pointer type can safely be cast to 'long long'. * But on 32-bit we need to avoid warnings about casting pointers to integers * of different sizes without truncating 64-bit values so 'long' or 'long long' * must be used depending on the size of the value.
@@ -66,12 +64,12 @@* them, but we do not use s128 types in the kernel (we do use 'u128', * but they are handled by the !is_signed_type() case). */ -#ifdef CONFIG_64BIT -#define __signed_type (ux) long +#if __SIZEOF_POINTER__ == __SIZEOF_LONG_LONG__ +#define __is_nonneg (ux) statically_true((long long)(ux) >= 0)#else -#define __signed_type (ux) typeof(__builtin_choose_expr(sizeof(ux) > 4, 1LL, 1L)) +#define __is_nonneg (ux) statically_true( \ + (typeof(__builtin_choose_expr(sizeof(ux) > 4, 1LL, 1L)))(ux) >= 0)#endif -#define __is_nonneg (ux) statically_true((__signed_type(ux))(ux) >= 0)#define __types_ok (ux, uy) \ (__sign_use(ux) & __sign_use(uy))
Greg Kroah-Hartman
maintainerPATCH 260/276 minixfs: Verify inode mode when loading from disk
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tetsuo Handa <[email protected]>
[ Upstream commit 73861970938ad1323eb02bbbc87f6fbd1e5bacca ]
The inode mode loaded from corrupted disk can be invalid. Do like what commit 0a9e74051313 ("isofs: Verify inode mode when loading from disk") does.
--- fs/minix/inode.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
fs/minix/inode.c +7 -1
@@ -470,8 +470,14 @@ void minix_set_inode(struct inode *inode, dev_t rdev) inode->i_op = &minix_symlink_inode_operations;inode_nohighmem (inode); inode->i_mapping->a_ops = &minix_aops; - }else + }else if (S_ISCHR (inode->i_mode) ||S_ISBLK (inode->i_mode) || +S_ISFIFO (inode->i_mode) ||S_ISSOCK (inode->i_mode)) {init_special_inode (inode, inode->i_mode, rdev); + }else { +printk (KERN_DEBUG "MINIX-fs: Invalid file type 0%04o for inode %lu.\n" , + inode->i_mode, inode->i_ino); +make_bad_inode (inode); + } }/*
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 261/276 pid: Add a judgment for ns null in pid_nr_ns
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: gaoxiang17 <[email protected]>
[ Upstream commit 006568ab4c5ca2309ceb36fa553e390b4aa9c0c7 ]
__task_pid_nr_ns
ns = task_active_pid_ns(current);
pid_nr_ns(rcu_dereference(*task_pid_ptr(task, type)), ns);
if (pid && ns->level <= pid->level) {Sometimes null is returned for task_active_pid_ns. Then it will trigger kernel panic in pid_nr_ns.
For example:
Unable to handle kernel NULL pointer dereference at virtual address 0000000000000058 Mem abort info: ESR = 0x0000000096000007 EC = 0x25: DABT (current EL), IL = 32 bits SET = 0, FnV = 0 EA = 0, S1PTW = 0 FSC = 0x07: level 3 translation fault Data abort info: ISV = 0, ISS = 0x00000007, ISS2 = 0x00000000 CM = 0, WnR = 0, TnD = 0, TagAccess = 0 GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0 user pgtable: 4k pages, 39-bit VAs, pgdp=00000002175aa000 [0000000000000058] pgd=08000002175ab003, p4d=08000002175ab003, pud=08000002175ab003, pmd=08000002175be003, pte=0000000000000000 pstate: 834000c5 (Nzcv daIF +PAN -UAO +TCO +DIT -SSBS BTYPE=--) pc : __task_pid_nr_ns+0x74/0xd0 lr : __task_pid_nr_ns+0x24/0xd0 sp : ffffffc08001bd10 x29: ffffffc08001bd10 x28: ffffffd4422b2000 x27: 0000000000000001 x26: ffffffd442821168 x25: ffffffd442821000 x24: 00000f89492eab31 x23: 00000000000000c0 x22: ffffff806f5693c0 x21: ffffff806f5693c0 x20: 0000000000000001 x19: 0000000000000000 x18: 0000000000000000 x17: 00000000529c6ef0 x16: 00000000529c6ef0 x15: 00000000023a1adc x14: 0000000000000003 x13: 00000000007ef6d8 x12: 001167c391c78800 x11: 00ffffffffffffff x10: 0000000000000000 x9 : 0000000000000001 x8 : ffffff80816fa3c0 x7 : 0000000000000000 x6 : 49534d702d535449 x5 : ffffffc080c4c2c0 x4 : ffffffd43ee128c8 x3 : ffffffd43ee124dc x2 : 0000000000000000 x1 : 0000000000000001 x0 : ffffff806f5693c0 Call trace: __task_pid_nr_ns+0x74/0xd0 ... __handle_irq_event_percpu+0xd4/0x284 handle_irq_event+0x48/0xb0 handle_fasteoi_irq+0x160/0x2d8 generic_handle_domain_irq+0x44/0x60 gic_handle_irq+0x4c/0x114 call_on_irq_stack+0x3c/0x74 do_interrupt_handler+0x4c/0x84 el1_interrupt+0x34/0x58 el1h_64_irq_handler+0x18/0x24 el1h_64_irq+0x68/0x6c account_kernel_stack+0x60/0x144 exit_task_stack_account+0x1c/0x80 do_exit+0x7e4/0xaf8 ... get_signal+0x7bc/0x8d8 do_notify_resume+0x128/0x828 el0_svc+0x6c/0x70 el0t_64_sync_handler+0x68/0xbc el0t_64_sync+0x1a8/0x1ac Code: 35fffe54 911a02a8 f9400108 b4000128 (b9405a69) ---[ end trace 0000000000000000 ]--- Kernel panic - not syncing: Oops: Fatal exception in interrupt
--- kernel/pid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/pid.c +1 -1
@@ -474,7 +474,7 @@ pid_t pid_nr_ns(struct pid *pid, struct pid_namespace *ns)struct upid *upid;pid_t nr =0 ; -if (pid && ns->level <= pid->level) { +if (pid && ns && ns->level <= pid->level) { upid = &pid->numbers[ns->level];if (upid->ns == ns) nr = upid->nr;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 262/276 pid: make __task_pid_nr_ns(ns => NULL) safe for zombie callers
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Oleg Nesterov <[email protected]>
[ Upstream commit abdfd4948e45c51b19162cf8b3f5003f8f53c9b9 ]
task_pid_vnr(another_task) will crash if the caller was already reaped. The pid_alive(current) check can't really help, the parent/debugger can call release_task() right after this check.
This also means that even task_ppid_nr_ns(current, NULL) is not safe, pid_alive() only ensures that it is safe to dereference ->real_parent.
Change __task_pid_nr_ns() to ensure ns != NULL.
--- kernel/pid.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
kernel/pid.c +2 -1
@@ -497,7 +497,8 @@ pid_t __task_pid_nr_ns(struct task_struct *task, enum pid_type type,rcu_read_lock ();if (!ns) ns =task_active_pid_ns (current); - nr =pid_nr_ns (rcu_dereference (*task_pid_ptr (task, type)), ns); +if (ns) + nr =pid_nr_ns (rcu_dereference (*task_pid_ptr (task, type)), ns);rcu_read_unlock ();return nr;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 263/276 fs: Add initramfs_options to set initramfs mount options
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lichen Liu <[email protected]>
[ Upstream commit 278033a225e13ec21900f0a92b8351658f5377f2 ]
When CONFIG_TMPFS is enabled, the initial root filesystem is a tmpfs. By default, a tmpfs mount is limited to using 50% of the available RAM for its content. This can be problematic in memory-constrained environments, particularly during a kdump capture.
In a kdump scenario, the capture kernel boots with a limited amount of memory specified by the 'crashkernel' parameter. If the initramfs is large, it may fail to unpack into the tmpfs rootfs due to insufficient space. This is because to get X MB of usable space in tmpfs, 2*X MB of memory must be available for the mount. This leads to an OOM failure during the early boot process, preventing a successful crash dump.
This patch introduces a new kernel command-line parameter, initramfs_options, which allows passing specific mount options directly to the rootfs when it is first mounted. This gives users control over the rootfs behavior.
For example, a user can now specify initramfs_options=size=75% to allow the tmpfs to use up to 75% of the available memory. This can significantly reduce the memory pressure for kdump.
Consider a practical example:
To unpack a 48MB initramfs, the tmpfs needs 48MB of usable space. With the default 50% limit, this requires a memory pool of 96MB to be available for the tmpfs mount. The total memory requirement is therefore
approximately: 16MB (vmlinuz) + 48MB (loaded initramfs) + 48MB (unpacked kernel) + 96MB (for tmpfs) + 12MB (runtime overhead) ≈ 220MB.
By using initramfs_options=size=75%, the memory pool required for the 48MB tmpfs is reduced to 48MB / 0.75 = 64MB. This reduces the total memory requirement by 32MB (96MB - 64MB), allowing the kdump to succeed with a smaller crashkernel size, such as 192MB.
An alternative approach of reusing the existing rootflags parameter was considered. However, a new, dedicated initramfs_options parameter was chosen to avoid altering the current behavior of rootflags (which applies to the final root filesystem) and to prevent any potential regressions.
Also add documentation for the new kernel parameter "initramfs_options"
This approach is inspired by prior discussions and patches on the topic.
Ref: https://www.lightofdawn.org/blog/?viewDetailed=00128
Ref: https://landley.net/notes-2015.html#01-01-2015
Ref: https://lkml.org/lkml/2021/6/29/783
Ref: https://www.kernel.org/doc/html/latest/filesystems/ramfs-rootfs-initramfs.html#what-is-rootfs
--- Documentation/admin-guide/kernel-parameters.txt | 3 +++ fs/namespace.c | 11 ++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-)
Documentation/admin-guide/kernel-parameters.txt +3 -0
@@ -5148,6 +5148,9 @@ rootflags= [KNL] Set root filesystem mount option string + initramfs_options= [KNL] + Specify mount options for for the initramfs mount. + rootfstype= [KNL] Set root filesystem type rootwait [KNL] Wait (indefinitely) for root device to show up.
fs/namespace.c +10 -1
@@ -64,6 +64,15 @@ static int __init set_mphash_entries(char *str) }__setup ("mphash_entries=" , set_mphash_entries); +static char *__initdata initramfs_options; +static int __init initramfs_options_setup (char *str) +{ + initramfs_options = str; +return 1 ; +} + +__setup ("initramfs_options=" , initramfs_options_setup); +static u64 event;static DEFINE_IDA (mnt_id_ida);static DEFINE_IDA (mnt_group_ida);
@@ -4352,7 +4361,7 @@ static void __init init_mount_tree(void)struct mnt_namespace *ns;struct path root; - mnt =vfs_kern_mount (&rootfs_fs_type,0 ,"rootfs" ,NULL ); + mnt =vfs_kern_mount (&rootfs_fs_type,0 ,"rootfs" , initramfs_options);if (IS_ERR (mnt))panic ("Can't create rootfs" );
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 264/276 cramfs: Verify inode mode when loading from disk
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tetsuo Handa <[email protected]>
[ Upstream commit 7f9d34b0a7cb93d678ee7207f0634dbf79e47fe5 ]
The inode mode loaded from corrupted disk can be invalid. Do like what commit 0a9e74051313 ("isofs: Verify inode mode when loading from disk") does.
--- fs/cramfs/inode.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)
fs/cramfs/inode.c +10 -1
@@ -117,9 +117,18 @@ static struct inode *get_cramfs_inode(struct super_block *sb,inode_nohighmem (inode); inode->i_data.a_ops = &cramfs_aops;break ; -default : +case S_IFCHR : +case S_IFBLK : +case S_IFIFO : +case S_IFSOCK :init_special_inode (inode, cramfs_inode->mode,old_decode_dev (cramfs_inode->size)); +break ; +default : +printk (KERN_DEBUG "CRAMFS: Invalid file type 0%04o for inode %lu.\n" , + inode->i_mode, inode->i_ino); +iget_failed (inode); +return ERR_PTR (-EIO ); } inode->i_mode = cramfs_inode->mode;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 265/276 writeback: Avoid softlockup when switching many inodes
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jan Kara <[email protected]>
[ Upstream commit 66c14dccd810d42ec5c73bb8a9177489dfd62278 ]
process_inode_switch_wbs_work() can be switching over 100 inodes to a different cgroup. Since switching an inode requires counting all dirty & under-writeback pages in the address space of each inode, this can take a significant amount of time. Add a possibility to reschedule after processing each inode to avoid softlockups.
--- fs/fs-writeback.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)
fs/fs-writeback.c +10 -1
@@ -475,6 +475,7 @@ static void inode_switch_wbs_work_fn(struct work_struct *work)*/ down_read (&bdi->wb_switch_rwsem); + inodep = isw->inodes;/* * By the time control reaches here, RCU grace period has passed * since I_WB_SWITCH assertion and all wb stat update transactions
@@ -485,6 +486,7 @@ static void inode_switch_wbs_work_fn(struct work_struct *work)* gives us exclusion against all wb related operations on @inode * including IO list manipulations and stat updates. */ +relock:if (old_wb < new_wb) {spin_lock (&old_wb->list_lock);spin_lock_nested (&new_wb->list_lock,SINGLE_DEPTH_NESTING );
@@ -493,10 +495,17 @@ static void inode_switch_wbs_work_fn(struct work_struct *work)spin_lock_nested (&old_wb->list_lock,SINGLE_DEPTH_NESTING ); } -for (inodep = isw->inodes; *inodep; inodep++) { +while (*inodep) {WARN_ON_ONCE ((*inodep)->i_wb != old_wb);if (inode_do_switch_wbs (*inodep, old_wb, new_wb)) nr_switched++; + inodep++; +if (*inodep &&need_resched ()) { +spin_unlock (&new_wb->list_lock); +spin_unlock (&old_wb->list_lock); +cond_resched (); + goto relock; + } }spin_unlock (&new_wb->list_lock);
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 266/276 writeback: Avoid excessively long inode switching times
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jan Kara <[email protected]>
[ Upstream commit 9a6ebbdbd41235ea3bc0c4f39e2076599b8113cc ]
With lazytime mount option enabled we can be switching many dirty inodes on cgroup exit to the parent cgroup. The numbers observed in practice when systemd slice of a large cron job exits can easily reach hundreds of thousands or millions. The logic in inode_do_switch_wbs() which sorts the inode into appropriate place in b_dirty list of the target wb however has linear complexity in the number of dirty inodes thus overall time complexity of switching all the inodes is quadratic leading to workers being pegged for hours consuming 100% of the CPU and switching inodes to the parent wb.
Simple reproducer of the issue:
FILES=10000
# Filesystem mounted with lazytime mount option
MNT=/mnt/
echo "Creating files and switching timestamps"
for (( j = 0; j < 50; j ++ )); do
mkdir $MNT/dir$j
for (( i = 0; i < $FILES; i++ )); do
echo "foo" >$MNT/dir$j/file$i
done
touch -a -t 202501010000 $MNT/dir$j/file* done
wait
echo "Syncing and flushing"
sync
echo 3 >/proc/sys/vm/drop_caches
echo "Reading all files from a cgroup"
mkdir /sys/fs/cgroup/unified/mycg1 || exit
echo $$ >/sys/fs/cgroup/unified/mycg1/cgroup.procs || exit
for (( j = 0; j < 50; j ++ )); do
cat /mnt/dir$j/file* >/dev/null &
done
wait
echo "Switching wbs"
# Now rmdir the cgroup after the script exitsWe need to maintain b_dirty list ordering to keep writeback happy so instead of sorting inode into appropriate place just append it at the end of the list and clobber dirtied_time_when. This may result in inode writeback starting later after cgroup switch however cgroup switches are rare so it shouldn't matter much. Since the cgroup had write access to the inode, there are no practical concerns of the possible DoS issues.
--- fs/fs-writeback.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-)
fs/fs-writeback.c +11 -10
@@ -418,22 +418,23 @@ static bool inode_do_switch_wbs(struct inode *inode,* Transfer to @new_wb's IO list if necessary. If the @inode is dirty, * the specific list @inode was on is ignored and the @inode is put on * ->b_dirty which is always correct including from ->b_dirty_time. -* The transfer preserves @inode->dirtied_when ordering. If the @inode -* was clean, it means it was on the b_attached list, so move it onto -* the b_attached list of @new_wb. +* If the @inode was clean, it means it was on the b_attached list, so +* move it onto the b_attached list of @new_wb. */ if (!list_empty (&inode->i_io_list)) { inode->i_wb = new_wb;if (inode->i_state &I_DIRTY_ALL ) { -struct inode *pos; - -list_for_each_entry (pos, &new_wb->b_dirty, i_io_list) -if (time_after_eq (inode->dirtied_when, - pos->dirtied_when)) -break ; +/* +* We need to keep b_dirty list sorted by +* dirtied_time_when. However properly sorting the +* inode in the list gets too expensive when switching +* many inodes. So just attach inode at the end of the +* dirty list and clobber the dirtied_time_when. +*/ + inode->dirtied_time_when = jiffies;inode_io_list_move_locked (inode, new_wb, - pos->i_io_list.prev); + &new_wb->b_dirty); }else {inode_cgwb_move_to_attached (inode, new_wb); }
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 267/276 media: switch from pci_ to dma_ API
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christophe JAILLET <[email protected]>
[ Upstream commit 887069f424550ebdcb411166733e1d05002b58e4 ]
The wrappers in include/linux/pci-dma-compat.h should go away.
The patch has been generated with the coccinelle script below.
It has been compile tested.
@@
@@
- PCI_DMA_BIDIRECTIONAL
+ DMA_BIDIRECTIONAL
@@
@@
- PCI_DMA_TODEVICE
+ DMA_TO_DEVICE
@@
@@
- PCI_DMA_FROMDEVICE
+ DMA_FROM_DEVICE
@@
@@
- PCI_DMA_NONE
+ DMA_NONE
@@
expression e1, e2, e3;
@@
- pci_alloc_consistent(e1, e2, e3)
+ dma_alloc_coherent(&e1->dev, e2, e3, GFP_)
@@
expression e1, e2, e3;
@@
- pci_zalloc_consistent(e1, e2, e3)
+ dma_alloc_coherent(&e1->dev, e2, e3, GFP_)
@@
expression e1, e2, e3, e4;
@@
- pci_free_consistent(e1, e2, e3, e4)
+ dma_free_coherent(&e1->dev, e2, e3, e4)
@@
expression e1, e2, e3, e4;
@@
- pci_map_single(e1, e2, e3, e4)
+ dma_map_single(&e1->dev, e2, e3, e4)
@@
expression e1, e2, e3, e4;
@@
- pci_unmap_single(e1, e2, e3, e4)
+ dma_unmap_single(&e1->dev, e2, e3, e4)
@@
expression e1, e2, e3, e4, e5;
@@
- pci_map_page(e1, e2, e3, e4, e5)
+ dma_map_page(&e1->dev, e2, e3, e4, e5)
@@
expression e1, e2, e3, e4;
@@
- pci_unmap_page(e1, e2, e3, e4)
+ dma_unmap_page(&e1->dev, e2, e3, e4)
@@
expression e1, e2, e3, e4;
@@
- pci_map_sg(e1, e2, e3, e4)
+ dma_map_sg(&e1->dev, e2, e3, e4)
@@
expression e1, e2, e3, e4;
@@
- pci_unmap_sg(e1, e2, e3, e4)
+ dma_unmap_sg(&e1->dev, e2, e3, e4)
@@
expression e1, e2, e3, e4;
@@
- pci_dma_sync_single_for_cpu(e1, e2, e3, e4)
+ dma_sync_single_for_cpu(&e1->dev, e2, e3, e4)
@@
expression e1, e2, e3, e4;
@@
- pci_dma_sync_single_for_device(e1, e2, e3, e4)
+ dma_sync_single_for_device(&e1->dev, e2, e3, e4)
@@
expression e1, e2, e3, e4;
@@
- pci_dma_sync_sg_for_cpu(e1, e2, e3, e4)
+ dma_sync_sg_for_cpu(&e1->dev, e2, e3, e4)
@@
expression e1, e2, e3, e4;
@@
- pci_dma_sync_sg_for_device(e1, e2, e3, e4)
+ dma_sync_sg_for_device(&e1->dev, e2, e3, e4)
@@
expression e1, e2;
@@
- pci_dma_mapping_error(e1, e2)
+ dma_mapping_error(&e1->dev, e2)
@@
expression e1, e2;
@@
- pci_set_dma_mask(e1, e2)
+ dma_set_mask(&e1->dev, e2)
@@
expression e1, e2;
@@
- pci_set_consistent_dma_mask(e1, e2)
+ dma_set_coherent_mask(&e1->dev, e2)
Stable-dep-of: 23b53639a793 ("media: cx18: Add missing check after DMA map")
--- drivers/media/pci/cobalt/cobalt-driver.c | 4 ++-- drivers/media/pci/cx18/cx18-driver.c | 2 +- drivers/media/pci/cx18/cx18-queue.c | 13 +++++++------ drivers/media/pci/cx18/cx18-streams.c | 16 ++++++++-------- drivers/media/pci/ddbridge/ddbridge-main.c | 4 ++-- drivers/media/pci/intel/ipu3/ipu3-cio2-main.c | 2 +- drivers/media/pci/netup_unidvb/netup_unidvb_core.c | 2 +- drivers/media/pci/pluto2/pluto2.c | 20 ++++++++++---------- drivers/media/pci/pt1/pt1.c | 2 +- drivers/media/pci/tw5864/tw5864-core.c | 2 +- 10 files changed, 34 insertions(+), 33 deletions(-)
drivers/media/pci/cobalt/cobalt-driver.c +2 -2
@@ -333,8 +333,8 @@ static int cobalt_setup_pci(struct cobal } } -if (pci_set_dma_mask (pci_dev,DMA_BIT_MASK (64 ))) { - ret =pci_set_dma_mask (pci_dev,DMA_BIT_MASK (32 )); +if (dma_set_mask (&pci_dev->dev,DMA_BIT_MASK (64 ))) { + ret =dma_set_mask (&pci_dev->dev,DMA_BIT_MASK (32 ));if (ret) {cobalt_err ("no suitable DMA available\n" ); goto err_disable;
drivers/media/pci/cx18/cx18-driver.c +1 -1
@@ -804,7 +804,7 @@ static int cx18_setup_pci(struct cx18 *cCX18_ERR ("Can't enable device %d!\n" , cx->instance);return -EIO ; } -if (pci_set_dma_mask (pci_dev,DMA_BIT_MASK (32 ))) { +if (dma_set_mask (&pci_dev->dev,DMA_BIT_MASK (32 ))) {CX18_ERR ("No suitable DMA available, card %d\n" , cx->instance);return -EIO ; }
drivers/media/pci/cx18/cx18-queue.c +7 -6
@@ -325,8 +325,8 @@ void _cx18_mdl_sync_for_device(struct cxstruct cx18_buffer *buf;list_for_each_entry (buf, &mdl->buf_list, list) -pci_dma_sync_single_for_device (pci_dev, buf->dma_handle, - buf_size, dma); +dma_sync_single_for_device (&pci_dev->dev, buf->dma_handle, + buf_size, dma); }int cx18_stream_alloc (struct cx18_stream *s)
@@ -385,8 +385,9 @@ int cx18_stream_alloc(struct cx18_streamcx18_enqueue (s, mdl, &s->q_idle);INIT_LIST_HEAD (&buf->list); - buf->dma_handle =pci_map_single (s->cx->pci_dev, - buf->buf, s->buf_size, s->dma); + buf->dma_handle =dma_map_single (&s->cx->pci_dev->dev, + buf->buf, s->buf_size, + s->dma);cx18_buf_sync_for_cpu (s, buf);list_add_tail (&buf->list, &s->buf_pool); }
@@ -419,8 +420,8 @@ void cx18_stream_free(struct cx18_stream buf = list_first_entry(&s->buf_pool, struct cx18_buffer, list);list_del_init (&buf->list); -pci_unmap_single (s->cx->pci_dev, buf->dma_handle, - s->buf_size, s->dma); +dma_unmap_single (&s->cx->pci_dev->dev, buf->dma_handle, + s->buf_size, s->dma);kfree (buf->buf);kfree (buf); }
drivers/media/pci/cx18/cx18-streams.c +8 -8
@@ -49,44 +49,44 @@ static struct { {/* CX18_ENC_STREAM_TYPE_MPG */ "encoder MPEG" ,VFL_TYPE_VIDEO ,0 , -PCI_DMA_FROMDEVICE , +DMA_FROM_DEVICE ,V4L2_CAP_VIDEO_CAPTURE |V4L2_CAP_READWRITE |V4L2_CAP_AUDIO |V4L2_CAP_TUNER }, { /* CX18_ENC_STREAM_TYPE_TS */"TS" ,VFL_TYPE_VIDEO ,-1 , -PCI_DMA_FROMDEVICE , +DMA_FROM_DEVICE , }, { /* CX18_ENC_STREAM_TYPE_YUV */"encoder YUV" ,VFL_TYPE_VIDEO ,CX18_V4L2_ENC_YUV_OFFSET , -PCI_DMA_FROMDEVICE , +DMA_FROM_DEVICE ,V4L2_CAP_VIDEO_CAPTURE |V4L2_CAP_READWRITE |V4L2_CAP_STREAMING |V4L2_CAP_AUDIO |V4L2_CAP_TUNER }, { /* CX18_ENC_STREAM_TYPE_VBI */"encoder VBI" ,VFL_TYPE_VBI ,0 , -PCI_DMA_FROMDEVICE , +DMA_FROM_DEVICE ,V4L2_CAP_VBI_CAPTURE |V4L2_CAP_SLICED_VBI_CAPTURE |V4L2_CAP_READWRITE |V4L2_CAP_TUNER }, { /* CX18_ENC_STREAM_TYPE_PCM */"encoder PCM audio" ,VFL_TYPE_VIDEO ,CX18_V4L2_ENC_PCM_OFFSET , -PCI_DMA_FROMDEVICE , +DMA_FROM_DEVICE ,V4L2_CAP_TUNER |V4L2_CAP_AUDIO |V4L2_CAP_READWRITE , }, { /* CX18_ENC_STREAM_TYPE_IDX */"encoder IDX" ,VFL_TYPE_VIDEO ,-1 , -PCI_DMA_FROMDEVICE , +DMA_FROM_DEVICE , }, { /* CX18_ENC_STREAM_TYPE_RAD */"encoder radio" ,VFL_TYPE_RADIO ,0 , -PCI_DMA_NONE , +DMA_NONE ,V4L2_CAP_RADIO |V4L2_CAP_TUNER }, };
@@ -324,7 +324,7 @@ static int cx18_prep_dev(struct cx18 *cx/* User explicitly selected 0 buffers for these streams, so don't create them. */ -if (cx18_stream_info[type].dma !=PCI_DMA_NONE && +if (cx18_stream_info[type].dma !=DMA_NONE && cx->stream_buffers[type] ==0 ) {CX18_INFO ("Disabled %s device\n" , cx18_stream_info[type].name);return 0 ;
drivers/media/pci/ddbridge/ddbridge-main.c +2 -2
@@ -180,8 +180,8 @@ static int ddb_probe(struct pci_dev *pdepci_set_master (pdev); -if (pci_set_dma_mask (pdev,DMA_BIT_MASK (64 ))) -if (pci_set_dma_mask (pdev,DMA_BIT_MASK (32 ))) +if (dma_set_mask (&pdev->dev,DMA_BIT_MASK (64 ))) +if (dma_set_mask (&pdev->dev,DMA_BIT_MASK (32 )))return -ENODEV ; dev =vzalloc (sizeof (*dev));
drivers/media/pci/intel/ipu3/ipu3-cio2-main.c +1 -1
@@ -1760,7 +1760,7 @@ static int cio2_pci_probe(struct pci_devpci_set_master (pci_dev); - r =pci_set_dma_mask (pci_dev,CIO2_DMA_MASK ); + r =dma_set_mask (&pci_dev->dev,CIO2_DMA_MASK );if (r) {dev_err (dev,"failed to set DMA mask (%d)\n" , r);return -ENODEV ;
drivers/media/pci/netup_unidvb/netup_unidvb_core.c +1 -1
@@ -846,7 +846,7 @@ static int netup_unidvb_initdev(struct p"%s(): board vendor 0x%x, revision 0x%x\n" , __func__, board_vendor, board_revision);pci_set_master (pci_dev); -if (pci_set_dma_mask (pci_dev,0xffffffff ) <0 ) { +if (dma_set_mask (&pci_dev->dev,0xffffffff ) <0 ) {dev_err (&pci_dev->dev,"%s(): 32bit PCI DMA is not supported\n" , __func__); goto pci_detect_err;
drivers/media/pci/pluto2/pluto2.c +10 -10
@@ -228,16 +228,16 @@ static void pluto_set_dma_addr(struct plstatic int pluto_dma_map (struct pluto *pluto) { - pluto->dma_addr =pci_map_single (pluto->pdev, pluto->dma_buf, -TS_DMA_BYTES ,PCI_DMA_FROMDEVICE ); + pluto->dma_addr =dma_map_single (&pluto->pdev->dev, pluto->dma_buf, +TS_DMA_BYTES ,DMA_FROM_DEVICE ); -return pci_dma_mapping_error (pluto->pdev, pluto->dma_addr); +return dma_mapping_error (&pluto->pdev->dev, pluto->dma_addr); }static void pluto_dma_unmap (struct pluto *pluto) { -pci_unmap_single (pluto->pdev, pluto->dma_addr, -TS_DMA_BYTES ,PCI_DMA_FROMDEVICE ); +dma_unmap_single (&pluto->pdev->dev, pluto->dma_addr,TS_DMA_BYTES , +DMA_FROM_DEVICE ); }static int pluto_start_feed (struct dvb_demux_feed *f)
@@ -276,8 +276,8 @@ static void pluto_dma_end(struct pluto * {/* synchronize the DMA transfer with the CPU * first so that we see updated contents. */ -pci_dma_sync_single_for_cpu (pluto->pdev, pluto->dma_addr, -TS_DMA_BYTES ,PCI_DMA_FROMDEVICE ); +dma_sync_single_for_cpu (&pluto->pdev->dev, pluto->dma_addr, +TS_DMA_BYTES ,DMA_FROM_DEVICE );/* Workaround for broken hardware: * [1] On startup NBPACKETS seems to contain an uninitialized value,
@@ -310,8 +310,8 @@ static void pluto_dma_end(struct pluto *pluto_set_dma_addr (pluto);/* sync the buffer and give it back to the card */ -pci_dma_sync_single_for_device (pluto->pdev, pluto->dma_addr, -TS_DMA_BYTES ,PCI_DMA_FROMDEVICE ); +dma_sync_single_for_device (&pluto->pdev->dev, pluto->dma_addr, +TS_DMA_BYTES ,DMA_FROM_DEVICE ); }static irqreturn_t pluto_irq (int irq,void *dev_id)
@@ -595,7 +595,7 @@ static int pluto2_probe(struct pci_dev */* enable interrupts */ pci_write_config_dword (pdev,0x6c ,0x8000 ); - ret =pci_set_dma_mask (pdev,DMA_BIT_MASK (32 )); + ret =dma_set_mask (&pdev->dev,DMA_BIT_MASK (32 ));if (ret <0 ) goto err_pci_disable_device;
drivers/media/pci/pt1/pt1.c +1 -1
@@ -1340,7 +1340,7 @@ static int pt1_probe(struct pci_dev *pdeif (ret <0 ) goto err; - ret =pci_set_dma_mask (pdev,DMA_BIT_MASK (32 )); + ret =dma_set_mask (&pdev->dev,DMA_BIT_MASK (32 ));if (ret <0 ) goto err_pci_disable_device;
drivers/media/pci/tw5864/tw5864-core.c +1 -1
@@ -262,7 +262,7 @@ static int tw5864_initdev(struct pci_devpci_set_master (pci_dev); - err =pci_set_dma_mask (pci_dev,DMA_BIT_MASK (32 )); + err =dma_set_mask (&pci_dev->dev,DMA_BIT_MASK (32 ));if (err) {dev_err (&dev->pci->dev,"32 bit PCI DMA is not supported\n" ); goto disable_pci;
Greg Kroah-Hartman
maintainerPATCH 268/276 media: cx18: Add missing check after DMA map
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thomas Fourier <[email protected]>
[ Upstream commit 23b53639a793477326fd57ed103823a8ab63084f ]
The DMA map functions can fail and should be tested for errors. If the mapping fails, dealloc buffers, and return.
--- drivers/media/pci/cx18/cx18-queue.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-)
drivers/media/pci/cx18/cx18-queue.c +10 -3
@@ -379,15 +379,22 @@ int cx18_stream_alloc(struct cx18_streambreak ; } + buf->dma_handle =dma_map_single (&s->cx->pci_dev->dev, + buf->buf, s->buf_size, + s->dma); +if (dma_mapping_error (&s->cx->pci_dev->dev, buf->dma_handle)) { +kfree (buf->buf); +kfree (mdl); +kfree (buf); +break ; + } +INIT_LIST_HEAD (&mdl->list);INIT_LIST_HEAD (&mdl->buf_list); mdl->id = s->mdl_base_idx;/* a somewhat safe value */ cx18_enqueue (s, mdl, &s->q_idle);INIT_LIST_HEAD (&buf->list); - buf->dma_handle =dma_map_single (&s->cx->pci_dev->dev, - buf->buf, s->buf_size, - s->dma);cx18_buf_sync_for_cpu (s, buf);list_add_tail (&buf->list, &s->buf_pool); }
Greg Kroah-Hartman
maintainerPATCH 269/276 arm64: mte: Do not flag the zero page as PG_mte_tagged
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Catalin Marinas <[email protected]>
[ Upstream commit f620d66af3165838bfa845dcf9f5f9b4089bf508 ]
Commit 68d54ceeec0e ("arm64: mte: Allow PTRACE_PEEKMTETAGS access to the zero page") attempted to fix ptrace() reading of tags from the zero page by marking it as PG_mte_tagged during cpu_enable_mte(). The same commit also changed the ptrace() tag access permission check to the VM_MTE vma flag while turning the page flag test into a WARN_ON_ONCE().
Attempting to set the PG_mte_tagged flag early with CONFIG_DEFERRED_STRUCT_PAGE_INIT enabled may either hang (after commit d77e59a8fccd "arm64: mte: Lock a page for MTE tag initialisation") or have the flags cleared later during page_alloc_init_late(). In addition, pages_identical() -> memcmp_pages() will reject any comparison with the zero page as it is marked as tagged.
Partially revert the above commit to avoid setting PG_mte_tagged on the zero page. Update the __access_remote_tags() warning on untagged pages to ignore the zero page since it is known to have the tags initialised.
Note that all user mapping of the zero page are marked as pte_special(). The arm64 set_pte_at() will not call mte_sync_tags() on such pages, so PG_mte_tagged will remain cleared.
--- arch/arm64/kernel/cpufeature.c | 10 ++++++++-- arch/arm64/kernel/mte.c | 3 ++- 2 files changed, 10 insertions(+), 3 deletions(-)
arch/arm64/kernel/cpufeature.c +8 -2
@@ -1948,16 +1948,22 @@ static void bti_enable(const struct arm6#ifdef CONFIG_ARM64_MTE static void cpu_enable_mte (struct arm64_cpu_capabilities const *cap) { +static bool cleared_zero_page = false; +sysreg_clear_set (sctlr_el1,0 , SCTLR_ELx_ATA |SCTLR_EL1_ATA0 );mte_cpu_setup ();/* * Clear the tags in the zero page. This needs to be done via the -* linear map which has the Tagged attribute. +* linear map which has the Tagged attribute. Since this page is +* always mapped as pte_special(), set_pte_at() will not attempt to +* clear the tags or set PG_mte_tagged. */ -if (!test_and_set_bit (PG_mte_tagged, &ZERO_PAGE (0 )->flags)) +if (!cleared_zero_page) { + cleared_zero_page = true;mte_clear_page_tags (lm_alias (empty_zero_page)); + }kasan_init_hw_tags_cpu (); }
arch/arm64/kernel/mte.c +2 -1
@@ -370,7 +370,8 @@ static int __access_remote_tags(struct mput_page (page);break ; } -WARN_ON_ONCE (!test_bit (PG_mte_tagged, &page->flags)); +WARN_ON_ONCE (!test_bit (PG_mte_tagged, &page->flags) && + !is_zero_pfn (page_to_pfn (page)));/* limit access to the end of the page */ offset =offset_in_page (addr);
Greg Kroah-Hartman
maintainerPATCH 270/276 media: pci/ivtv: switch from pci_ to dma_ API
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christophe JAILLET <[email protected]>
[ Upstream commit 1932dc2f4cf6ac23e48e5fcc24d21adbe35691d1 ]
The wrappers in include/linux/pci-dma-compat.h should go away.
The patch has been generated with the coccinelle script below. It has been compile tested.
No memory allocation in involved in this patch, so no GFP_ tweak is needed.
@@ @@
- PCI_DMA_BIDIRECTIONAL
+ DMA_BIDIRECTIONAL
@@ @@
- PCI_DMA_TODEVICE
+ DMA_TO_DEVICE
@@ @@
- PCI_DMA_FROMDEVICE
+ DMA_FROM_DEVICE
@@ @@
- PCI_DMA_NONE
+ DMA_NONE
@@
expression e1, e2, e3;
@@
- pci_alloc_consistent(e1, e2, e3)
+ dma_alloc_coherent(&e1->dev, e2, e3, GFP_)
@@
expression e1, e2, e3;
@@
- pci_zalloc_consistent(e1, e2, e3)
+ dma_alloc_coherent(&e1->dev, e2, e3, GFP_)
@@
expression e1, e2, e3, e4;
@@
- pci_free_consistent(e1, e2, e3, e4)
+ dma_free_coherent(&e1->dev, e2, e3, e4)
@@
expression e1, e2, e3, e4;
@@
- pci_map_single(e1, e2, e3, e4)
+ dma_map_single(&e1->dev, e2, e3, e4)
@@
expression e1, e2, e3, e4;
@@
- pci_unmap_single(e1, e2, e3, e4)
+ dma_unmap_single(&e1->dev, e2, e3, e4)
@@
expression e1, e2, e3, e4, e5;
@@
- pci_map_page(e1, e2, e3, e4, e5)
+ dma_map_page(&e1->dev, e2, e3, e4, e5)
@@
expression e1, e2, e3, e4;
@@
- pci_unmap_page(e1, e2, e3, e4)
+ dma_unmap_page(&e1->dev, e2, e3, e4)
@@
expression e1, e2, e3, e4;
@@
- pci_map_sg(e1, e2, e3, e4)
+ dma_map_sg(&e1->dev, e2, e3, e4)
@@
expression e1, e2, e3, e4;
@@
- pci_unmap_sg(e1, e2, e3, e4)
+ dma_unmap_sg(&e1->dev, e2, e3, e4)
@@
expression e1, e2, e3, e4;
@@
- pci_dma_sync_single_for_cpu(e1, e2, e3, e4)
+ dma_sync_single_for_cpu(&e1->dev, e2, e3, e4)
@@
expression e1, e2, e3, e4;
@@
- pci_dma_sync_single_for_device(e1, e2, e3, e4)
+ dma_sync_single_for_device(&e1->dev, e2, e3, e4)
@@
expression e1, e2, e3, e4;
@@
- pci_dma_sync_sg_for_cpu(e1, e2, e3, e4)
+ dma_sync_sg_for_cpu(&e1->dev, e2, e3, e4)
@@
expression e1, e2, e3, e4;
@@
- pci_dma_sync_sg_for_device(e1, e2, e3, e4)
+ dma_sync_sg_for_device(&e1->dev, e2, e3, e4)
@@
expression e1, e2;
@@
- pci_dma_mapping_error(e1, e2)
+ dma_mapping_error(&e1->dev, e2)
@@
expression e1, e2;
@@
- pci_set_dma_mask(e1, e2)
+ dma_set_mask(&e1->dev, e2)
@@
expression e1, e2;
@@
- pci_set_consistent_dma_mask(e1, e2)
+ dma_set_coherent_mask(&e1->dev, e2)
Stable-dep-of: 1069a4fe637d ("media: pci: ivtv: Add missing check after DMA map")
--- drivers/media/pci/ivtv/ivtv-driver.c | 2 +- drivers/media/pci/ivtv/ivtv-queue.c | 18 ++++++++++-------- drivers/media/pci/ivtv/ivtv-streams.c | 22 +++++++++++----------- drivers/media/pci/ivtv/ivtv-udma.c | 19 ++++++++++++------- drivers/media/pci/ivtv/ivtv-yuv.c | 10 +++++++--- 5 files changed, 41 insertions(+), 30 deletions(-)
drivers/media/pci/ivtv/ivtv-driver.c +1 -1
@@ -837,7 +837,7 @@ static int ivtv_setup_pci(struct ivtv *iIVTV_ERR ("Can't enable device!\n" );return -EIO ; } -if (pci_set_dma_mask (pdev,DMA_BIT_MASK (32 ))) { +if (dma_set_mask (&pdev->dev,DMA_BIT_MASK (32 ))) {IVTV_ERR ("No suitable DMA available.\n" );return -EIO ; }
drivers/media/pci/ivtv/ivtv-queue.c +10 -8
@@ -188,7 +188,7 @@ int ivtv_stream_alloc(struct ivtv_streamreturn 0 ;IVTV_DEBUG_INFO ("Allocate %s%s stream: %d x %d buffers (%dkB total)\n" , - s->dma !=PCI_DMA_NONE ?"DMA " :"" , + s->dma !=DMA_NONE ?"DMA " :"" , s->name, s->buffers, s->buf_size, s->buffers * s->buf_size /1024 ); s->sg_pending =kzalloc (SGsize,GFP_KERNEL |__GFP_NOWARN);
@@ -218,8 +218,9 @@ int ivtv_stream_alloc(struct ivtv_streamreturn -ENOMEM ; }if (ivtv_might_use_dma (s)) { - s->sg_handle =pci_map_single (itv->pdev, s->sg_dma, -sizeof (struct ivtv_sg_element ),PCI_DMA_TODEVICE ); + s->sg_handle =dma_map_single (&itv->pdev->dev, s->sg_dma, +sizeof (struct ivtv_sg_element ), +DMA_TO_DEVICE );ivtv_stream_sync_for_cpu (s); }
@@ -237,7 +238,7 @@ int ivtv_stream_alloc(struct ivtv_stream }INIT_LIST_HEAD (&buf->list);if (ivtv_might_use_dma (s)) { - buf->dma_handle =pci_map_single (s->itv->pdev, + buf->dma_handle =dma_map_single (&s->itv->pdev->dev, buf->buf, s->buf_size +256 , s->dma);ivtv_buf_sync_for_cpu (s, buf); }
@@ -260,8 +261,8 @@ void ivtv_stream_free(struct ivtv_stream/* empty q_free */ while ((buf =ivtv_dequeue (s, &s->q_free))) {if (ivtv_might_use_dma (s)) -pci_unmap_single (s->itv->pdev, buf->dma_handle, - s->buf_size +256 , s->dma); +dma_unmap_single (&s->itv->pdev->dev, buf->dma_handle, + s->buf_size +256 , s->dma);kfree (buf->buf);kfree (buf); }
@@ -269,8 +270,9 @@ void ivtv_stream_free(struct ivtv_stream/* Free SG Array/Lists */ if (s->sg_dma !=NULL ) {if (s->sg_handle !=IVTV_DMA_UNMAPPED ) { -pci_unmap_single (s->itv->pdev, s->sg_handle, -sizeof (struct ivtv_sg_element ),PCI_DMA_TODEVICE ); +dma_unmap_single (&s->itv->pdev->dev, s->sg_handle, +sizeof (struct ivtv_sg_element ), +DMA_TO_DEVICE ); s->sg_handle =IVTV_DMA_UNMAPPED ; }kfree (s->sg_pending);
drivers/media/pci/ivtv/ivtv-streams.c +11 -11
@@ -100,7 +100,7 @@ static struct { {/* IVTV_ENC_STREAM_TYPE_MPG */ "encoder MPG" ,VFL_TYPE_VIDEO ,0 , -PCI_DMA_FROMDEVICE ,0 , +DMA_FROM_DEVICE ,0 ,V4L2_CAP_VIDEO_CAPTURE |V4L2_CAP_TUNER |V4L2_CAP_AUDIO |V4L2_CAP_READWRITE , &ivtv_v4l2_enc_fops
@@ -108,7 +108,7 @@ static struct { {/* IVTV_ENC_STREAM_TYPE_YUV */ "encoder YUV" ,VFL_TYPE_VIDEO ,IVTV_V4L2_ENC_YUV_OFFSET , -PCI_DMA_FROMDEVICE ,0 , +DMA_FROM_DEVICE ,0 ,V4L2_CAP_VIDEO_CAPTURE |V4L2_CAP_TUNER |V4L2_CAP_AUDIO |V4L2_CAP_READWRITE , &ivtv_v4l2_enc_fops
@@ -116,7 +116,7 @@ static struct { {/* IVTV_ENC_STREAM_TYPE_VBI */ "encoder VBI" ,VFL_TYPE_VBI ,0 , -PCI_DMA_FROMDEVICE ,0 , +DMA_FROM_DEVICE ,0 ,V4L2_CAP_VBI_CAPTURE |V4L2_CAP_SLICED_VBI_CAPTURE |V4L2_CAP_TUNER |V4L2_CAP_AUDIO |V4L2_CAP_READWRITE , &ivtv_v4l2_enc_fops
@@ -124,42 +124,42 @@ static struct { {/* IVTV_ENC_STREAM_TYPE_PCM */ "encoder PCM" ,VFL_TYPE_VIDEO ,IVTV_V4L2_ENC_PCM_OFFSET , -PCI_DMA_FROMDEVICE ,0 , +DMA_FROM_DEVICE ,0 ,V4L2_CAP_TUNER |V4L2_CAP_AUDIO |V4L2_CAP_READWRITE , &ivtv_v4l2_enc_fops }, { /* IVTV_ENC_STREAM_TYPE_RAD */"encoder radio" ,VFL_TYPE_RADIO ,0 , -PCI_DMA_NONE ,1 , +DMA_NONE ,1 ,V4L2_CAP_RADIO |V4L2_CAP_TUNER , &ivtv_v4l2_radio_fops }, { /* IVTV_DEC_STREAM_TYPE_MPG */"decoder MPG" ,VFL_TYPE_VIDEO ,IVTV_V4L2_DEC_MPG_OFFSET , -PCI_DMA_TODEVICE ,0 , +DMA_TO_DEVICE ,0 ,V4L2_CAP_VIDEO_OUTPUT |V4L2_CAP_AUDIO |V4L2_CAP_READWRITE , &ivtv_v4l2_dec_fops }, { /* IVTV_DEC_STREAM_TYPE_VBI */"decoder VBI" ,VFL_TYPE_VBI ,IVTV_V4L2_DEC_VBI_OFFSET , -PCI_DMA_NONE ,1 , +DMA_NONE ,1 ,V4L2_CAP_SLICED_VBI_CAPTURE |V4L2_CAP_READWRITE , &ivtv_v4l2_enc_fops }, { /* IVTV_DEC_STREAM_TYPE_VOUT */"decoder VOUT" ,VFL_TYPE_VBI ,IVTV_V4L2_DEC_VOUT_OFFSET , -PCI_DMA_NONE ,1 , +DMA_NONE ,1 ,V4L2_CAP_SLICED_VBI_OUTPUT |V4L2_CAP_AUDIO |V4L2_CAP_READWRITE , &ivtv_v4l2_dec_fops }, { /* IVTV_DEC_STREAM_TYPE_YUV */"decoder YUV" ,VFL_TYPE_VIDEO ,IVTV_V4L2_DEC_YUV_OFFSET , -PCI_DMA_TODEVICE ,0 , +DMA_TO_DEVICE ,0 ,V4L2_CAP_VIDEO_OUTPUT |V4L2_CAP_AUDIO |V4L2_CAP_READWRITE , &ivtv_v4l2_dec_fops }
@@ -179,7 +179,7 @@ static void ivtv_stream_init(struct ivtv s->vdev.device_caps = ivtv_stream_info[type].v4l2_caps;if (ivtv_stream_info[type].pio) - s->dma =PCI_DMA_NONE ; + s->dma =DMA_NONE ;else s->dma = ivtv_stream_info[type].dma; s->buf_size = itv->stream_buf_size[type];
@@ -217,7 +217,7 @@ static int ivtv_prep_dev(struct ivtv *it/* User explicitly selected 0 buffers for these streams, so don't create them. */ -if (ivtv_stream_info[type].dma !=PCI_DMA_NONE && +if (ivtv_stream_info[type].dma !=DMA_NONE && itv->options.kilobytes[type] ==0 ) {IVTV_INFO ("Disabled %s device\n" , ivtv_stream_info[type].name);return 0 ;
drivers/media/pci/ivtv/ivtv-udma.c +12 -7
@@ -81,8 +81,10 @@ void ivtv_udma_alloc(struct ivtv *itv) {if (itv->udma.SG_handle ==0 ) {/* Map DMA Page Array Buffer */ - itv->udma.SG_handle =pci_map_single (itv->pdev, itv->udma.SGarray, -sizeof (itv->udma.SGarray),PCI_DMA_TODEVICE ); + itv->udma.SG_handle =dma_map_single (&itv->pdev->dev, + itv->udma.SGarray, +sizeof (itv->udma.SGarray), +DMA_TO_DEVICE );ivtv_udma_sync_for_cpu (itv); } }
@@ -135,7 +137,8 @@ int ivtv_udma_setup(struct ivtv *itv, un }/* Map SG List */ - dma->SG_length =pci_map_sg (itv->pdev, dma->SGlist, dma->page_count,PCI_DMA_TODEVICE ); + dma->SG_length =dma_map_sg (&itv->pdev->dev, dma->SGlist, + dma->page_count,DMA_TO_DEVICE );/* Fill SG Array with new values */ ivtv_udma_fill_sg_array (dma, ivtv_dest_addr,0 ,-1 );
@@ -159,7 +162,8 @@ void ivtv_udma_unmap(struct ivtv *itv)/* Unmap Scatterlist */ if (dma->SG_length) { -pci_unmap_sg (itv->pdev, dma->SGlist, dma->page_count,PCI_DMA_TODEVICE ); +dma_unmap_sg (&itv->pdev->dev, dma->SGlist, dma->page_count, +DMA_TO_DEVICE ); dma->SG_length =0 ; }/* sync DMA */
@@ -175,13 +179,14 @@ void ivtv_udma_free(struct ivtv *itv)/* Unmap SG Array */ if (itv->udma.SG_handle) { -pci_unmap_single (itv->pdev, itv->udma.SG_handle, -sizeof (itv->udma.SGarray),PCI_DMA_TODEVICE ); +dma_unmap_single (&itv->pdev->dev, itv->udma.SG_handle, +sizeof (itv->udma.SGarray),DMA_TO_DEVICE ); }/* Unmap Scatterlist */ if (itv->udma.SG_length) { -pci_unmap_sg (itv->pdev, itv->udma.SGlist, itv->udma.page_count,PCI_DMA_TODEVICE ); +dma_unmap_sg (&itv->pdev->dev, itv->udma.SGlist, + itv->udma.page_count,DMA_TO_DEVICE ); }for (i =0 ; i <IVTV_DMA_SG_OSD_ENT ; i++) {
drivers/media/pci/ivtv/ivtv-yuv.c +7 -3
@@ -113,7 +113,8 @@ static int ivtv_yuv_prep_user_dma(struct dma->page_count =0 ;return -ENOMEM ; } - dma->SG_length =pci_map_sg (itv->pdev, dma->SGlist, dma->page_count,PCI_DMA_TODEVICE ); + dma->SG_length =dma_map_sg (&itv->pdev->dev, dma->SGlist, + dma->page_count,DMA_TO_DEVICE );/* Fill SG Array with new values */ ivtv_udma_fill_sg_array (dma, y_buffer_offset, uv_buffer_offset, y_size);
@@ -920,7 +921,9 @@ static void ivtv_yuv_init(struct ivtv *i/* We need a buffer for blanking when Y plane is offset - non-fatal if we can't get one */ yi->blanking_ptr =kzalloc (720 *16 ,GFP_ATOMIC |__GFP_NOWARN);if (yi->blanking_ptr) { - yi->blanking_dmaptr =pci_map_single (itv->pdev, yi->blanking_ptr,720 *16 ,PCI_DMA_TODEVICE ); + yi->blanking_dmaptr =dma_map_single (&itv->pdev->dev, + yi->blanking_ptr, +720 *16 ,DMA_TO_DEVICE ); }else { yi->blanking_dmaptr =0 ;IVTV_DEBUG_WARN ("Failed to allocate yuv blanking buffer\n" );
@@ -1264,7 +1267,8 @@ void ivtv_yuv_close(struct ivtv *itv)if (yi->blanking_ptr) {kfree (yi->blanking_ptr); yi->blanking_ptr =NULL ; -pci_unmap_single (itv->pdev, yi->blanking_dmaptr,720 *16 ,PCI_DMA_TODEVICE ); +dma_unmap_single (&itv->pdev->dev, yi->blanking_dmaptr, +720 *16 ,DMA_TO_DEVICE ); }/* Invalidate the old dimension information */
Greg Kroah-Hartman
maintainerPATCH 271/276 media: pci: ivtv: Add missing check after DMA map
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thomas Fourier <[email protected]>
[ Upstream commit 1069a4fe637d0e3e4c163e3f8df9be306cc299b4 ]
The DMA map functions can fail and should be tested for errors. If the mapping fails, free blanking_ptr and set it to 0. As 0 is a valid DMA address, use blanking_ptr to test if the DMA address is set.
--- drivers/media/pci/ivtv/ivtv-irq.c | 2 +- drivers/media/pci/ivtv/ivtv-yuv.c | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-)
drivers/media/pci/ivtv/ivtv-irq.c +1 -1
@@ -351,7 +351,7 @@ void ivtv_dma_stream_dec_prepare(struct/* Insert buffer block for YUV if needed */ if (s->type ==IVTV_DEC_STREAM_TYPE_YUV && f->offset_y) { -if (yi->blanking_dmaptr) { +if (yi->blanking_ptr) { s->sg_pending[idx].src = yi->blanking_dmaptr; s->sg_pending[idx].dst = offset; s->sg_pending[idx].size =720 *16 ;
drivers/media/pci/ivtv/ivtv-yuv.c +7 -1
@@ -120,7 +120,7 @@ static int ivtv_yuv_prep_user_dma(structivtv_udma_fill_sg_array (dma, y_buffer_offset, uv_buffer_offset, y_size);/* If we've offset the y plane, ensure top area is blanked */ -if (f->offset_y && yi->blanking_dmaptr) { +if (f->offset_y && yi->blanking_ptr) { dma->SGarray[dma->SG_length].size =cpu_to_le32 (720 *16 ); dma->SGarray[dma->SG_length].src =cpu_to_le32 (yi->blanking_dmaptr); dma->SGarray[dma->SG_length].dst =cpu_to_le32 (IVTV_DECODER_OFFSET + yuv_offset[frame]);
@@ -924,6 +924,12 @@ static void ivtv_yuv_init(struct ivtv *i yi->blanking_dmaptr =dma_map_single (&itv->pdev->dev, yi->blanking_ptr,720 *16 ,DMA_TO_DEVICE ); +if (dma_mapping_error (&itv->pdev->dev, yi->blanking_dmaptr)) { +kfree (yi->blanking_ptr); + yi->blanking_ptr =NULL ; + yi->blanking_dmaptr =0 ; +IVTV_DEBUG_WARN ("Failed to dma_map yuv blanking buffer\n" ); + } }else { yi->blanking_dmaptr =0 ;IVTV_DEBUG_WARN ("Failed to allocate yuv blanking buffer\n" );
Greg Kroah-Hartman
maintainerPATCH 272/276 xen/events: Update virq_to_irq on migration
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jason Andryuk <[email protected]>
[ Upstream commit 3fcc8e146935415d69ffabb5df40ecf50e106131 ]
VIRQs come in 3 flavors, per-VPU, per-domain, and global, and the VIRQs are tracked in per-cpu virq_to_irq arrays.
Per-domain and global VIRQs must be bound on CPU 0, and bind_virq_to_irq() sets the per_cpu virq_to_irq at registration time Later, the interrupt can migrate, and info->cpu is updated. When calling __unbind_from_irq(), the per-cpu virq_to_irq is cleared for a different cpu. If bind_virq_to_irq() is called again with CPU 0, the stale irq is returned. There won't be any irq_info for the irq, so things break.
Make xen_rebind_evtchn_to_cpu() update the per_cpu virq_to_irq mappings to keep them update to date with the current cpu. This ensures the correct virq_to_irq is cleared in __unbind_from_irq().
Message-ID: <[email protected]>
--- drivers/xen/events/events_base.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-)
drivers/xen/events/events_base.c +12 -1
@@ -1820,9 +1820,20 @@ static int xen_rebind_evtchn_to_cpu(stru* virq or IPI channel, which don't actually need to be rebound. Ignore * it, but don't do the xenlinux-level rebind in that case. */ -if (HYPERVISOR_event_channel_op (EVTCHNOP_bind_vcpu, &bind_vcpu) >=0 ) +if (HYPERVISOR_event_channel_op (EVTCHNOP_bind_vcpu, &bind_vcpu) >=0 ) { +int old_cpu = info->cpu; +bind_evtchn_to_cpu (evtchn, tcpu, false); +if (info->type ==IRQT_VIRQ ) { +int virq = info->u.virq; +int irq =per_cpu (virq_to_irq, old_cpu)[virq]; + +per_cpu (virq_to_irq, old_cpu)[virq] =-1 ; +per_cpu (virq_to_irq, tcpu)[virq] = irq; + } + } +do_unmask (info,EVT_MASK_REASON_TEMPORARY );return 0 ;
Greg Kroah-Hartman
maintainerPATCH 273/276 media: pci: ivtv: Add check for DMA map result
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mikhail Kobuk <[email protected]>
commit 629913d6d79508b166c66e07e4857e20233d85a9 upstream.
In case DMA fails, 'dma->SG_length' is 0. This value is later used to access 'dma->SGarray[dma->SG_length - 1]', which will cause out of bounds access.
Add check to return early on invalid value. Adjust warnings accordingly.
Found by Linux Verification Center (linuxtesting.org) with SVACE.
--- drivers/media/pci/ivtv/ivtv-udma.c | 8 ++++++++ drivers/media/pci/ivtv/ivtv-yuv.c | 6 ++++++ drivers/media/pci/ivtv/ivtvfb.c | 6 +++--- 3 files changed, 17 insertions(+), 3 deletions(-)
drivers/media/pci/ivtv/ivtv-udma.c +8 -0
@@ -131,6 +131,8 @@ int ivtv_udma_setup(struct ivtv *itv, un/* Fill SG List with new values */ if (ivtv_udma_fill_sg_list (dma, &user_dma,0 ) <0 ) { +IVTV_DEBUG_WARN ("%s: could not allocate bounce buffers for highmem userspace buffers\n" , + __func__);unpin_user_pages (dma->map, dma->page_count); dma->page_count =0 ;return -ENOMEM ;
@@ -139,6 +141,12 @@ int ivtv_udma_setup(struct ivtv *itv, un/* Map SG List */ dma->SG_length =dma_map_sg (&itv->pdev->dev, dma->SGlist, dma->page_count,DMA_TO_DEVICE ); +if (!dma->SG_length) { +IVTV_DEBUG_WARN ("%s: DMA map error, SG_length is 0\n" , __func__); +unpin_user_pages (dma->map, dma->page_count); + dma->page_count =0 ; +return -EINVAL ; + }/* Fill SG Array with new values */ ivtv_udma_fill_sg_array (dma, ivtv_dest_addr,0 ,-1 );
drivers/media/pci/ivtv/ivtv-yuv.c +6 -0
@@ -115,6 +115,12 @@ static int ivtv_yuv_prep_user_dma(struct } dma->SG_length =dma_map_sg (&itv->pdev->dev, dma->SGlist, dma->page_count,DMA_TO_DEVICE ); +if (!dma->SG_length) { +IVTV_DEBUG_WARN ("%s: DMA map error, SG_length is 0\n" , __func__); +unpin_user_pages (dma->map, dma->page_count); + dma->page_count =0 ; +return -EINVAL ; + }/* Fill SG Array with new values */ ivtv_udma_fill_sg_array (dma, y_buffer_offset, uv_buffer_offset, y_size);
drivers/media/pci/ivtv/ivtvfb.c +3 -3
@@ -281,10 +281,10 @@ static int ivtvfb_prep_dec_dma_to_device/* Map User DMA */ if (ivtv_udma_setup (itv, ivtv_dest_addr, userbuf, size_in_bytes) <=0 ) {mutex_unlock (&itv->udma.lock); -IVTVFB_WARN ("ivtvfb_prep_dec_dma_to_device, Error with pin_user_pages: %d bytes, %d pages returned\n" , - size_in_bytes, itv->udma.page_count); +IVTVFB_WARN ("%s, Error in ivtv_udma_setup: %d bytes, %d pages returned\n" , + __func__, size_in_bytes, itv->udma.page_count); -/* pin_user_pages must have failed completely */ +/* pin_user_pages or DMA must have failed completely */ return -EIO ; }
Greg Kroah-Hartman
maintainerPATCH 274/276 mm/slab: make __free(kfree) accept error pointers
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dan Carpenter <[email protected]>
commit cd7eb8f83fcf258f71e293f7fc52a70be8ed0128 upstream.
Currently, if an automatically freed allocation is an error pointer that will lead to a crash. An example of this is in wm831x_gpio_dbg_show().
171 char *label __free(kfree) = gpiochip_dup_line_label(chip, i);
172 if (IS_ERR(label)) {
173 dev_err(wm831x->dev, "Failed to duplicate label\n");
174 continue;
175 }The auto clean up function should check for error pointers as well, otherwise we're going to keep hitting issues like this.
--- include/linux/slab.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
include/linux/slab.h +1 -1
@@ -187,7 +187,7 @@ void kfree(const void *objp);void kfree_sensitive (const void *objp);size_t __ksize (const void *objp); -DEFINE_FREE(kfree, void *, if (_T) kfree(_T)) +DEFINE_FREE(kfree, void *, if (!IS_ERR_OR_NULL(_T)) kfree(_T))/** * ksize - Report actual allocation size of associated object
Greg Kroah-Hartman
maintainerPATCH 275/276 mptcp: pm: in-kernel: usable client side with C-flag
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: "Matthieu Baerts (NGI0)" <[email protected]>
commit 4b1ff850e0c1aacc23e923ed22989b827b9808f9 upstream.
When servers set the C-flag in their MP_CAPABLE to tell clients not to create subflows to the initial address and port, clients will likely not use their other endpoints. That's because the in-kernel path-manager uses the 'subflow' endpoints to create subflows only to the initial address and port.
If the limits have not been modified to accept ADD_ADDR, the client doesn't try to establish new subflows. If the limits accept ADD_ADDR, the routing routes will be used to select the source IP.
The C-flag is typically set when the server is operating behind a legacy Layer 4 load balancer, or using anycast IP address. Clients having their different 'subflow' endpoints setup, don't end up creating multiple subflows as expected, and causing some deployment issues.
A special case is then added here: when servers set the C-flag in the MPC and directly sends an ADD_ADDR, this single ADD_ADDR is accepted. The 'subflows' endpoints will then be used with this new remote IP and port. This exception is only allowed when the ADD_ADDR is sent immediately after the 3WHS, and makes the client switching to the 'fully established' mode. After that, 'select_local_address()' will not be able to find any subflows, because 'id_avail_bitmap' will be filled in mptcp_pm_create_subflow_or_signal_addr(), when switching to 'fully established' mode.
[ Conflict in pm.c, because commit 498d7d8b75f1 ("mptcp: pm: remove
'_nl' from mptcp_pm_nl_is_init_remote_addr") renamed an helper in the context, and it is not in this version. The same new code can be applied at the same place.
Another conflict in pm.c, because commit 4d25247d3ae4 ("mptcp: bypass in-kernel PM restrictions for non-kernel PMs") switched the modified 'if' statement to an 'else if', and is not in this version. The same modification can still be applied.
Conflict in pm_kernel.c, because the modified code has been moved from pm_netlink.c to pm_kernel.c in commit 8617e85e04bd ("mptcp: pm: split in-kernel PM specific code"), which is not in this version. The resolution is easy: simply by applying the patch where 'pm_kernel.c' has been replaced 'pm_netlink.c'.
Conflict in pm_netlink.c, because commit b83fbca1b4c9 ("mptcp: pm:
reduce entries iterations on connect") is not in this version. Instead of using the 'locals' variable (struct mptcp_pm_local *) from the new version and embedding a "struct mptcp_addr_info", we can simply continue to use the 'addrs' variable (struct mptcp_addr_info *). Because commit b9d69db87fb7 ("mptcp: let the in-kernel PM use mixed IPv4 and IPv6 addresses") is not in this version, it is also required to pass an extra parameter to fill_local_addresses_vec(): struct mptcp_addr_info *remote, which is available from the caller side. Same with commit 4638de5aefe5 ("mptcp: handle local addrs announced by userspace PMs") adding the 'mptcp_' prefix to addresses_equal(). Conflict in protocol.h, because commit af3dc0ad3167 ("mptcp: Remove unused declaration mptcp_sockopt_sync()") is not in this version and it removed one line in the context. The resolution is easy because the new function can still be added at the same place. A similar conflict has been resolved due to commit 95d686517884 ("mptcp: fix subflow accounting on close"). ]
--- net/mptcp/pm.c | 7 +++++-- net/mptcp/pm_netlink.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++- net/mptcp/protocol.h | 8 ++++++++ 3 files changed, 61 insertions(+), 3 deletions(-)
net/mptcp/pm.c +5 -2
@@ -189,9 +189,12 @@ void mptcp_pm_add_addr_received(struct mspin_lock_bh (&pm->lock); -/* id0 should not have a different address */ +/* - id0 should not have a different address +* - special case for C-flag: linked to fill_local_addresses_vec() +*/ if ((addr->id ==0 && !mptcp_pm_nl_is_init_remote_addr (msk, addr)) || - (addr->id >0 && !READ_ONCE (pm->accept_addr))) { + (addr->id >0 && !READ_ONCE (pm->accept_addr) && + !mptcp_pm_add_addr_c_flag_case (msk))) {mptcp_pm_announce_addr (msk, addr, true);mptcp_pm_add_addr_send_ack (msk); }else if (mptcp_pm_schedule_work (msk,MPTCP_PM_ADD_ADDR_RECEIVED )) {
net/mptcp/pm_netlink.c +48 -1
83 lines not on this page · raw message
net/mptcp/protocol.h +8 -0
@@ -846,6 +846,14 @@ unsigned int mptcp_pm_get_add_addr_accepunsigned int mptcp_pm_get_subflows_max (const struct mptcp_sock *msk);unsigned int mptcp_pm_get_local_addr_max (const struct mptcp_sock *msk); +static inline bool mptcp_pm_add_addr_c_flag_case (struct mptcp_sock *msk) +{ +return READ_ONCE (msk->pm.remote_deny_join_id0) && + msk->pm.local_addr_used ==0 && +mptcp_pm_get_add_addr_accept_max (msk) ==0 && + msk->pm.subflows <mptcp_pm_get_subflows_max (msk); +} +void mptcp_sockopt_sync (struct mptcp_sock *msk,struct sock *ssk);void mptcp_sockopt_sync_all (struct mptcp_sock *msk);
Greg Kroah-Hartman
maintainerPATCH 276/276 selftests: mptcp: join: validate C-flag + def limit
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: "Matthieu Baerts (NGI0)" <[email protected]>
commit 008385efd05e04d8dff299382df2e8be0f91d8a0 upstream.
The previous commit adds an exception for the C-flag case. The 'mptcp_join.sh' selftest is extended to validate this case.
In this subtest, there is a typical CDN deployment with a client where MPTCP endpoints have been 'automatically' configured:
- the server set net.mptcp.allow_join_initial_addr_port=0
- the client has multiple 'subflow' endpoints, and the default limits:
not accepting ADD_ADDRs.
Without the parent patch, the client is not able to establish new subflows using its 'subflow' endpoints. The parent commit fixes that.
The 'Fixes' tag here below is the same as the one from the previous
commit: this patch here is not fixing anything wrong in the selftests, but it validates the previous fix for an issue introduced by this commit ID.
[ Conflicts in mptcp_join.sh, because many different helpers have been
modified in newer kernel versions, e.g. in commit 03668c65d153 ("selftests: mptcp: join: rework detailed report"), or commit 985de45923e2 ("selftests: mptcp: centralize stats dumping"), etc. Adaptations have been made to use the old way, similar to what is done just above. ]
--- tools/testing/selftests/net/mptcp/mptcp_join.sh | 10 ++++++++++ 1 file changed, 10 insertions(+)
tools/testing/selftests/net/mptcp/mptcp_join.sh +10 -0
@@ -1826,6 +1826,16 @@ deny_join_id0_tests() ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow run_tests $ns1 $ns2 10.0.1.1 chk_join_nr "subflow and address allow join id0 2" 1 1 1 + + # default limits, server deny join id 0 + signal + reset_with_allow_join_id0 0 1 + ip netns exec $ns1 ./pm_nl_ctl limits 0 2 + ip netns exec $ns2 ./pm_nl_ctl limits 0 2 + ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 flags signal + ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow + ip netns exec $ns2 ./pm_nl_ctl add 10.0.4.2 flags subflow + run_tests $ns1 $ns2 10.0.1.1 + chk_join_nr "default limits, server deny join id 0" 2 2 2 } fullmesh_tests()
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 5.15.195 release. There are 276 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Sun, 19 Oct 2025 14:50:59 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 8 lines
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.15.195-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-5.15.y
and the diffstat can be found below.thanks,
greg k-h
All tests passing for Tegra ...
Test results for stable-v5.15:
10 builds: 10 pass, 0 fail
28 boots: 28 pass, 0 fail
105 tests: 105 pass, 0 failLinux version: 5.15.195-rc1-g06cf22cc87e0
Boards tested: tegra124-jetson-tk1, tegra186-p2771-0000,
tegra186-p3509-0000+p3636-0001, tegra194-p2972-0000,
tegra194-p3509-0000+p3668-0000, tegra20-ventana,
tegra210-p2371-2180, tegra210-p3450-0000,
tegra30-cardhu-a04Jon
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 5.15.195 release. There are 276 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Sun, 19 Oct 2025 14:50:59 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 8 lines
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.15.195-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-5.15.y
and the diffstat can be found below.thanks,
greg k-h
perf fails to build on ARM, ARM64 and MIPS with:
In file included from util/arm-spe.c:37:
/local/users/fainelli/buildroot/output/arm/build/linux-custom/tools/include/../../arch/arm64/include/asm/cputype.h:198:10: fatal error: asm/sysreg.h: No such file or directory
198 | #include <asm/sysreg.h>
| ^~~~~~~~~~~~~~
compilation terminated.
I was not able to run a bisection but will attempt to do that later during the weekend.
Signature · 1 line
Florian
+Ali,
Quoted 21 lines · Florian Fainelli
Quoted 14 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 5.15.195 release. There are 276 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Sun, 19 Oct 2025 14:50:59 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/ patch-5.15.195-rc1.gz or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable- rc.git linux-5.15.y and the diffstat can be found below.Quoted 3 lines
thanks,
greg k-h
perf fails to build on ARM, ARM64 and MIPS with:
Quoted 7 lines
In file included from
util/arm-spe.c:37:
/local/users/fainelli/buildroot/output/arm/build/linux-custom/tools/include/../../arch/arm64/include/asm/cputype.h:198:10: fatal error: asm/sysreg.h: No such file or directory
198 | #include <asm/sysreg.h>
| ^~~~~~~~~~~~~~
compilation terminated.I was not able to run a bisection but will attempt to do that later during the weekend.
That is due to commit 07b49160816a936be7c1e0af869097223e75d547
Author: Ali Saidi <[email protected]> Date: Thu Aug 11 14:24:39 2022 +0800
perf arm-spe: Use SPE data source for neoverse cores
and this hunk specifically:
tools/perf/util/arm-spe.c +1 -0
@@ -34,6 +34,7 @@#include "arm-spe-decoder/arm-spe-decoder.h" #include "arm-spe-decoder/arm-spe-pkt-decoder.h" +#include "../../arch/arm64/include/asm/cputype.h" #define MAX_TIMESTAMP (~0ULL)
There is a dependency on this upstream commit:
commit 1314376d495f2d79cc58753ff3034ccc503c43c9
Author: Ali Saidi <[email protected]> Date: Thu Mar 24 18:33:20 2022 +0000
tools arm64: Import cputype.h
for tools/arch/arm64/include/asm/cputype.h to be present.
Signature · 1 line
Florian
Greg Kroah-Hartman
maintainerQuoted 58 lines · Florian Fainelli
+Ali,
Quoted 31 lines · Florian Fainelli
Quoted 16 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 5.15.195 release. There are 276 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Sun, 19 Oct 2025 14:50:59 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/
patch-5.15.195-rc1.gz
or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-
rc.git linux-5.15.y
and the diffstat can be found below.Quoted 3 lines
thanks,
greg k-h
perf fails to build on ARM, ARM64 and MIPS with:
In file included from
util/arm-spe.c:37:
/local/users/fainelli/buildroot/output/arm/build/linux-custom/tools/include/../../arch/arm64/include/asm/cputype.h:198:10: fatal error: asm/sysreg.h: No such file or directory
198 | #include <asm/sysreg.h>
| ^~~~~~~~~~~~~~
compilation terminated.Quoted 2 lines
I was not able to run a bisection but will attempt to do that later during the weekend.
That is due to commit
07b49160816a936be7c1e0af869097223e75d547Author: Ali Saidi <[email protected]> Date: Thu Aug 11 14:24:39 2022 +0800perf arm-spe: Use SPE data source for neoverse cores
and this hunk specifically:
tools/perf/util/arm-spe.c +1
-0@@ -34,6 +34,7 @@#include "arm-spe-decoder/arm-spe-decoder.h" #include "arm-spe-decoder/arm-spe-pkt-decoder.h" +#include "../../arch/arm64/include/asm/cputype.h" #define MAX_TIMESTAMP (~0ULL)There is a dependency on this upstream commit:
Quoted 8 lines
commit
1314376d495f2d79cc58753ff3034ccc503c43c9Author: Ali Saidi <[email protected]> Date: Thu Mar 24 18:33:20 2022 +0000tools arm64: Import
cputype.hfor
tools/arch/arm64/include/asm/cputype.hto be present.
Thanks, all offending commits now dropped :)
greg k-h
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 5.15.195 release. There are 276 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Sun, 19 Oct 2025 14:50:59 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 9 lines
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.15.195-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-5.15.y
and the diffstat can be found below.thanks,
greg k-h
Compiled and booted on my test system. No dmesg regressions.
thanks,
-- Shuah
# Librecast Test Results
020/020 [ OK ] liblcrq
010/010 [ OK ] libmld
120/120 [ OK ] liblibrecast
CPU/kernel: Linux auntie 5.15.195-rc1-00277-g06cf22cc87e0 #114 SMP Sat Oct 18 08:32:29 -00 2025 x86_64 AMD Ryzen 9 9950X 16-Core Processor AuthenticAMD GNU/Linux
Quoted 10 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 5.15.195 release. There are 276 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Sun, 19 Oct 2025 14:50:59 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 8 lines
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.15.195-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-5.15.y
and the diffstat can be found below.thanks,
greg k-h
The S390 build failed on stable-rc 5.15.195-rc1 with gcc-12, gcc-8 and clang-21 due to following build warnings / errors.
### Build error:drivers/s390/cio/device.c: In function 'purge_fn':drivers/s390/cio/device.c:1330:23: error: passing argument 1 of 'spin_lock_irq' from incompatible pointer type [-Werror=incompatible-pointer-types]
1330 | spin_lock_irq(&sch->lock);
| ^~~~~~~~~~
| |
| spinlock_t ** {aka struct spinlock **}In file included from drivers/s390/cio/device.c:16:include/linux/spinlock.h:387:55: note: expected 'spinlock_t *' {aka 'struct spinlock *'} but argument is of type 'spinlock_t **' {aka 'struct spinlock **'}
387 | static __always_inline void spin_lock_irq(spinlock_t *lock)
| ~~~~~~~~~~~~^~~~
drivers/s390/cio/device.c:1353:25: error: passing argument 1 of
'spin_unlock_irq' from incompatible pointer type
[-Werror=incompatible-pointer-types]
1353 | spin_unlock_irq(&sch->lock);
| ^~~~~~~~~~
| |
| spinlock_t ** {aka struct spinlock **}include/linux/spinlock.h:412:57: note: expected 'spinlock_t *' {aka 'struct spinlock *'} but argument is of type 'spinlock_t **' {aka 'struct spinlock **'}
412 | static __always_inline void spin_unlock_irq(spinlock_t *lock)
| ~~~~~~~~~~~~^~~~
cc1: some warnings being treated as errors
make[3]: *** [scripts/Makefile.build:289: drivers/s390/cio/device.o] Error 1
### Suspecting patches
Suspecting commit,
s390/cio: Update purge function to unregister the unused subchannels [ Upstream commit 9daa5a8795865f9a3c93d8d1066785b07ded6073 ]
Build regressions: 5.15.195-rc1: S390: cio/device.c:1330:23: error:
passing argument 1 of 'spin_lock_irq' from incompatible pointer type
## Build
* Build log: https://storage.tuxsuite.com/public/linaro/lkft/builds/34CVOf1lD7sJImDyWLFpIY7OBMW/build.log
* Build details:
https://regressions.linaro.org/lkft/linux-stable-rc-linux-5.15.y/v5.15.194-277-g06cf22cc87e0/build/gcc-12-defconfig/
* Build plan: https://tuxapi.tuxsuite.com/v1/groups/linaro/projects/lkft/builds/34CVOf1lD7sJImDyWLFpIY7OBMW
* Build link: https://storage.tuxsuite.com/public/linaro/lkft/builds/34CVOf1lD7sJImDyWLFpIY7OBMW/
* Kernel config:
https://storage.tuxsuite.com/public/linaro/lkft/builds/34CVOf1lD7sJImDyWLFpIY7OBMW/config
### Steps to reproduce
- tuxmake --runtime podman --target-arch s390 --toolchain gcc-12
--kconfig defconfig
## Build
* kernel: 5.15.195-rc1
* git: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git
* git commit: 06cf22cc87e00b878c310d5441981b7750f04078
* git describe: v5.15.194-277-g06cf22cc87e0
* test details:
https://qa-reports.linaro.org/lkft/linux-stable-rc-linux-5.15.y/build/v5.15.194-277-g06cf22cc87e0
## Test Regressions (compared to v5.15.193-152-g2e59a3f5f544)
* s390, build
- gcc-12-allnoconfig
- gcc-12-defconfig
- gcc-12-tinyconfig
- gcc-8-allnoconfig
- gcc-8-defconfig-fe40093d
- gcc-8-tinyconfig
## Metric Regressions (compared to v5.15.193-152-g2e59a3f5f544)
## Test Fixes (compared to v5.15.193-152-g2e59a3f5f544)
## Metric Fixes (compared to v5.15.193-152-g2e59a3f5f544)
## Test result summary
total: 54723, pass: 44299, fail: 2433, skip: 7666, xfail: 325
## Build Summary
* arc: 5 total, 5 passed, 0 failed
* arm: 101 total, 101 passed, 0 failed
* arm64: 28 total, 27 passed, 1 failed
* i386: 18 total, 18 passed, 0 failed
* mips: 22 total, 22 passed, 0 failed
* parisc: 3 total, 3 passed, 0 failed
* powerpc: 22 total, 22 passed, 0 failed
* riscv: 8 total, 8 passed, 0 failed
* s390: 9 total, 0 passed, 9 failed
* sh: 10 total, 10 passed, 0 failed
* sparc: 6 total, 6 passed, 0 failed
* x86_64: 24 total, 24 passed, 0 failed
## Test suites summary
* boot
* kselftest-arm64
* kselftest-breakpoints
* kselftest-capabilities
* kselftest-clone3
* kselftest-core
* kselftest-cpu-hotplug
* kselftest-exec
* kselftest-fpu
* kselftest-futex
* kselftest-intel_pstate
* kselftest-kcmp
* kselftest-livepatch
* kselftest-membarrier
* kselftest-mincore
* kselftest-mm
* kselftest-mqueue
* kselftest-net
* kselftest-net-mptcp
* kselftest-openat2
* kselftest-ptrace
* kselftest-rseq
* kselftest-rtc
* kselftest-seccomp
* kselftest-sigaltstack
* kselftest-size
* kselftest-tc-testing
* kselftest-timers
* kselftest-tmpfs
* kselftest-tpm2
* kselftest-user_events
* kselftest-vDSO
* kselftest-x86
* kunit
* kvm-unit-tests
* lava
* libgpiod
* libhugetlbfs
* log-parser-boot
* log-parser-build-clang
* log-parser-build-gcc
* log-parser-test
* ltp-capability
* ltp-commands
* ltp-containers
* ltp-controllers
* ltp-cpuhotplug
* ltp-crypto
* ltp-cve
* ltp-dio
* ltp-fcntl-locktests
* ltp-fs
* ltp-fs_bind
* ltp-fs_perms_simple
* ltp-hugetlb
* ltp-math
* ltp-mm
* ltp-nptl
* ltp-pty
* ltp-sched
* ltp-smoke
* ltp-syscalls
* ltp-tracing
* perf
* rcutorture
--
Linaro LKFT
https://lkft.linaro.org
Greg Kroah-Hartman
maintainerQuoted 57 lines · Naresh Kamboju
Quoted 10 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 5.15.195 release. There are 276 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Sun, 19 Oct 2025 14:50:59 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 8 lines
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.15.195-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-5.15.y
and the diffstat can be found below.thanks,
greg k-h
The S390 build failed on stable-rc 5.15.195-rc1 with gcc-12, gcc-8 and clang-21 due to following build warnings / errors.
### Build error:
drivers/s390/cio/device.c: In function 'purge_fn':drivers/s390/cio/device.c:1330:23: error: passing argument 1 of 'spin_lock_irq' from incompatible pointer type [-Werror=incompatible-pointer-types]1330 | spin_lock_irq(&sch->lock); | ^~~~~~~~~~ | | | spinlock_t ** {aka struct spinlock **}In file included from
drivers/s390/cio/device.c:16:include/linux/spinlock.h:387:55: note: expected 'spinlock_t*' {aka 'struct spinlock *'} but argument is of type 'spinlock_t**' {aka 'struct spinlock **'}
387 | static__always_inlinevoidspin_lock_irq(spinlock_t *lock)| ~~~~~~~~~~~~^~~~ drivers/s390/cio/device.c:1353:25: error: passing argument 1 of 'spin_unlock_irq' from incompatible pointer type [-Werror=incompatible-pointer-types] 1353 | spin_unlock_irq(&sch->lock); | ^~~~~~~~~~ | | | spinlock_t ** {aka struct spinlock **}
include/linux/spinlock.h:412:57: note: expected 'spinlock_t*' {aka 'struct spinlock *'} but argument is of type 'spinlock_t**' {aka 'struct spinlock **'}
412 | static__always_inlinevoidspin_unlock_irq(spinlock_t *lock)| ~~~~~~~~~~~~^~~~cc1: some warnings being treated as errors
make[3]: *** [scripts/Makefile.build:289:drivers/s390/cio/device.o] Error 1### Suspecting patches
Suspecting commit,
Quoted 8 lines
s390/cio: Update purge function to unregister the unused subchannels [ Upstream commit
9daa5a8795865f9a3c93d8d1066785b07ded6073]Build regressions: 5.15.195-rc1: S390:
cio/device.c:1330:23: error:
passing argument 1 of 'spin_lock_irq' from incompatible pointer type
Thanks for the report, I'll go drop this from all 3 queues now.
greg k-h