6.6.157-rc1 review
Subsystems (5)
Greg Kroah-Hartman
maintainerPATCH 839/1424 RDMA/nldev: Fix locking when accessing mr->pd
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jason Gunthorpe <[email protected]>
[ Upstream commit 50d5c02ab8e62325548bd3a6e6b758a9dcd6e7c3 ]
Sashiko points out that, due to rereg_mr, the PD is actually variable and all the touches in nldev are racy.
Use mr->device instead of mr->pd->device.
Getting the PD restrack ID is more tricky. To avoid disturbing all the happy paths, add an rdma_restrack_sync() operation which is sort of like flush_workqueue() or synchronize_irq(): after it returns, all the old nldev touches to the mr are gone and everything sees the new PD. This makes it safe to reach into the PD pointer.
Stable-dep-of: 709ba0e5311b ("RDMA/core: Fix use after free in ib_query_qp()")
--- drivers/infiniband/core/nldev.c | 15 +++++---- drivers/infiniband/core/restrack.c | 49 ++++++++++++++++++++++++++++ drivers/infiniband/core/restrack.h | 1 + drivers/infiniband/core/uverbs_cmd.c | 10 ++++-- include/rdma/ib_verbs.h | 5 +++ 5 files changed, 72 insertions(+), 8 deletions(-)
drivers/infiniband/core/nldev.c +9 -6
@@ -662,7 +662,7 @@ static int fill_res_mr_entry(struct sk_buff *msg, bool has_cap_net_admin, struct rdma_restrack_entry *res, uint32_t port) { struct ib_mr *mr = container_of(res, struct ib_mr, res); -struct ib_device *dev = mr->pd->device; +struct ib_device *dev = mr->device;if (has_cap_net_admin) {if (nla_put_u32 (msg,RDMA_NLDEV_ATTR_RES_RKEY , mr->rkey))
@@ -678,9 +678,12 @@ static int fill_res_mr_entry(struct sk_buff *msg, bool has_cap_net_admin,if (nla_put_u32 (msg,RDMA_NLDEV_ATTR_RES_MRN , res->id))return -EMSGSIZE ; -if (!rdma_is_kernel_res (res) && -nla_put_u32 (msg,RDMA_NLDEV_ATTR_RES_PDN , mr->pd->res.id)) -return -EMSGSIZE ; +if (!rdma_is_kernel_res (res)) { +struct ib_pd *pd =READ_ONCE (mr->pd); + +if (nla_put_u32 (msg,RDMA_NLDEV_ATTR_RES_PDN , pd->res.id)) +return -EMSGSIZE ; + }if (fill_res_name_pid (msg, res))return -EMSGSIZE ;
@@ -694,7 +697,7 @@ static int fill_res_mr_raw_entry(struct sk_buff *msg, bool has_cap_net_admin, struct rdma_restrack_entry *res, uint32_t port) { struct ib_mr *mr = container_of(res, struct ib_mr, res); -struct ib_device *dev = mr->pd->device; +struct ib_device *dev = mr->device;if (!dev->ops.fill_res_mr_entry_raw)return -EINVAL ;
@@ -966,7 +969,7 @@ static int fill_stat_mr_entry(struct sk_buff *msg, bool has_cap_net_admin, struct rdma_restrack_entry *res, uint32_t port) { struct ib_mr *mr = container_of(res, struct ib_mr, res); -struct ib_device *dev = mr->pd->device; +struct ib_device *dev = mr->device;if (nla_put_u32 (msg,RDMA_NLDEV_ATTR_RES_MRN , res->id)) goto err;
drivers/infiniband/core/restrack.c +49 -0
61 lines not on this page · raw message
drivers/infiniband/core/restrack.h +1 -0
@@ -27,6 +27,7 @@ int rdma_restrack_init(struct ib_device *dev);void rdma_restrack_clean (struct ib_device *dev);void rdma_restrack_add (struct rdma_restrack_entry *res);void rdma_restrack_del (struct rdma_restrack_entry *res); +void rdma_restrack_sync (struct rdma_restrack_entry *res);void rdma_restrack_new (struct rdma_restrack_entry *res,enum rdma_restrack_type type); void rdma_restrack_set_name(struct rdma_restrack_entry *res,
drivers/infiniband/core/uverbs_cmd.c +8 -2
@@ -46,6 +46,7 @@#include "uverbs.h" #include "core_priv.h" +#include "restrack.h" /* * Copy a response to userspace. If the provided 'resp' is larger than the
@@ -813,6 +814,10 @@ static int ib_uverbs_rereg_mr(struct uverbs_attr_bundle *attrs) ret =PTR_ERR (new_pd); goto put_uobjs; } +if (new_pd == orig_pd) { +uobj_put_obj_read (new_pd); + cmd.flags &= ~IB_MR_REREG_PD ; + } }else { new_pd = mr->pd; }
@@ -858,9 +863,10 @@ static int ib_uverbs_rereg_mr(struct uverbs_attr_bundle *attrs) mr = new_mr; }else {if (cmd.flags &IB_MR_REREG_PD ) { -atomic_dec (&orig_pd->usecnt); - mr->pd = new_pd;atomic_inc (&new_pd->usecnt); +WRITE_ONCE (mr->pd, new_pd); +rdma_restrack_sync (&mr->res); +atomic_dec (&orig_pd->usecnt); }if (cmd.flags &IB_MR_REREG_TRANS ) { mr->iova = cmd.hca_va;
include/rdma/ib_verbs.h +5 -0
@@ -1829,6 +1829,11 @@ struct ib_dm {struct ib_mr {struct ib_device *device; +/* +* Due to IB_MR_REREG_PD pd is not a fixed pointer and can change. For a +* user MR, this value should only be read from a system call that holds +* the uobject lock, or the driver should disable in-place REREG_PD. +*/ struct ib_pd *pd;u32 lkey;u32 rkey;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 840/1424 RDMA/core: Add rdma_restrack_begin/abort/commit_del() operations
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Patrisious Haddad <[email protected]>
[ Upstream commit 8d186210677c0322db886973bcec9aa4d21b51cd ]
Add rdma_restrack_abort_del(), rdma_restrack_begin_del() and rdma_restrack_commit_del() functions to allow deleting a resource from the xarray to effectively prevent future access to it and wait for all current users to finish while preserving its index in the xarray to allow to re-insert it if needed with guaranteed success.
This is a preparatory change for subsequent patches in the series which will use these functions to fix the cleanup flow.
Stable-dep-of: 709ba0e5311b ("RDMA/core: Fix use after free in ib_query_qp()")
--- drivers/infiniband/core/restrack.c | 165 +++++++++++++++++++++++------ drivers/infiniband/core/restrack.h | 3 + 2 files changed, 135 insertions(+), 33 deletions(-)
drivers/infiniband/core/restrack.c +132 -33
@@ -127,6 +127,46 @@ static void rdma_restrack_attach_task(struct rdma_restrack_entry *res, res->user = true; } +static struct rdma_restrack_root *res_to_rt (struct rdma_restrack_entry *res) +{ +struct ib_device *dev =res_to_dev (res); + +if (WARN_ON (!dev)) +return NULL ; + +return &dev->res[res->type]; +} + +static void restrack_drain_res (struct rdma_restrack_root *rt, +struct rdma_restrack_entry *res) +{ +if (rt) { +struct rdma_restrack_entry *old; + + old =xa_cmpxchg (&rt->xa, res->id, res,XA_ZERO_ENTRY , +GFP_KERNEL ); +WARN_ON (old != res); + } + +rdma_restrack_put (res); +wait_for_completion (&res->comp); +} + +static void restrack_restore_res (struct rdma_restrack_root *rt, +struct rdma_restrack_entry *res) +{ +reinit_completion (&res->comp); +kref_init (&res->kref); + +if (rt) { +struct rdma_restrack_entry *old; + + old =xa_cmpxchg (&rt->xa, res->id,XA_ZERO_ENTRY , res, +GFP_KERNEL ); +WARN_ON (old); + } +} +/** * rdma_restrack_set_name() - set the task for this resource * @res: resource entry
@@ -175,22 +215,23 @@ void rdma_restrack_new(struct rdma_restrack_entry *res,EXPORT_SYMBOL (rdma_restrack_new);/** -* rdma_restrack_add() - add object to the resource tracking database +* rdma_restrack_add() - add object to the resource tracking database. +* If this resource reuses an ID of a resource that was already destroyed +* after calling rdma_restrack_begin() but didn't yet call +* rdma_restrack_commit_del() it can result in an untracked QP. * @res: resource entry */ void rdma_restrack_add (struct rdma_restrack_entry *res) { -struct ib_device *dev =res_to_dev (res);struct rdma_restrack_root *rt;int ret =0 ; -if (!dev) -return ; -if (res->no_track) goto out; - rt = &dev->res[res->type]; + rt =res_to_rt (res); +if (!rt) +return ;if (res->type ==RDMA_RESTRACK_QP ) {/* Special case to ensure that LQPN points to right QP */
@@ -227,6 +268,28 @@ void rdma_restrack_add(struct rdma_restrack_entry *res) }EXPORT_SYMBOL (rdma_restrack_add); +/** +* rdma_restrack_abort_del() - re-add object to the resource tracking database +* it can only be used after rdma_restrack_begin_del(). +* @res: resource entry +*/ +void rdma_restrack_abort_del (struct rdma_restrack_entry *res) +{ +struct rdma_restrack_root *rt =NULL ; + +if (!res->valid) +return ; + +if (!res->no_track) { + rt =res_to_rt (res); +if (!rt) +return ; + } + +restrack_restore_res (rt, res); +} +EXPORT_SYMBOL (rdma_restrack_abort_del); +int __must_check rdma_restrack_get (struct rdma_restrack_entry *res) {return kref_get_unless_zero (&res->kref);
@@ -263,7 +326,7 @@ static void restrack_release(struct kref *kref)struct rdma_restrack_entry *res; res = container_of(kref, struct rdma_restrack_entry, kref); -if (res->task) { +if (res->task && !res->valid) {put_task_struct (res->task); res->task =NULL ; }
@@ -289,37 +352,20 @@ EXPORT_SYMBOL(rdma_restrack_put);*/ void rdma_restrack_sync (struct rdma_restrack_entry *res) { -struct rdma_restrack_entry *old;struct rdma_restrack_root *rt; -struct task_struct *task; -struct ib_device *dev;if (!res->valid || res->no_track)return ; - dev =res_to_dev (res); -if (WARN_ON (!dev)) + rt =res_to_rt (res); +if (!rt)return ; - rt = &dev->res[res->type];if (WARN_ON (xa_get_mark (&rt->xa, res->id,RESTRACK_DD )))return ; - old =xa_cmpxchg (&rt->xa, res->id, res,XA_ZERO_ENTRY ,GFP_KERNEL ); -if (WARN_ON (old != res)) -return ; - - task = res->task; -if (task) -get_task_struct (task); -rdma_restrack_put (res); -wait_for_completion (&res->comp); -reinit_completion (&res->comp); -if (task) - res->task = task; -kref_init (&res->kref); - -xa_cmpxchg (&rt->xa, res->id,XA_ZERO_ENTRY , res,GFP_KERNEL ); +restrack_drain_res (rt, res); +restrack_restore_res (rt, res); }EXPORT_SYMBOL (rdma_restrack_sync);
@@ -331,7 +377,6 @@ void rdma_restrack_del(struct rdma_restrack_entry *res) {struct rdma_restrack_entry *old;struct rdma_restrack_root *rt; -struct ib_device *dev;if (!res->valid) {if (res->task) {
@@ -344,12 +389,10 @@ void rdma_restrack_del(struct rdma_restrack_entry *res)if (res->no_track) goto out; - dev =res_to_dev (res); -if (WARN_ON (!dev)) + rt =res_to_rt (res); +if (!rt)return ; - rt = &dev->res[res->type]; - old =xa_erase (&rt->xa, res->id);WARN_ON (old != res);
@@ -357,5 +400,61 @@ void rdma_restrack_del(struct rdma_restrack_entry *res) res->valid = false;rdma_restrack_put (res);wait_for_completion (&res->comp); +if (res->task) { +put_task_struct (res->task); + res->task =NULL ; + } }EXPORT_SYMBOL (rdma_restrack_del); + +/** +* rdma_restrack_begin_del() - invalidate the object from the resource tracking +* database but preserve its index in the array. +* Since this preserves the index in the array until rdma_restrack_commit_del() +* is called, if rdma_restrack_add() is called in between with an old QP ID it +* can result in an untracked QP. +* @res: resource entry +*/ +void rdma_restrack_begin_del (struct rdma_restrack_entry *res) +{ +struct rdma_restrack_root *rt =NULL ; + +if (!res->valid) +return ; + +if (!res->no_track) { + rt =res_to_rt (res); +if (!rt) +return ; + } + +restrack_drain_res (rt, res); +} +EXPORT_SYMBOL (rdma_restrack_begin_del); + +/** +* rdma_restrack_commit_del() - delete object from the resource tracking +* database and free the task. +* @res: resource entry +*/ +void rdma_restrack_commit_del (struct rdma_restrack_entry *res) +{ +struct rdma_restrack_root *rt; + +if (!res->valid || res->no_track) + goto out; + + rt =res_to_rt (res); +if (!rt) +return ; + +xa_erase (&rt->xa, res->id); + +out: + res->valid = false; +if (res->task) { +put_task_struct (res->task); + res->task =NULL ; + } +} +EXPORT_SYMBOL (rdma_restrack_commit_del);
drivers/infiniband/core/restrack.h +3 -0
@@ -26,8 +26,11 @@ struct rdma_restrack_root {int rdma_restrack_init (struct ib_device *dev);void rdma_restrack_clean (struct ib_device *dev);void rdma_restrack_add (struct rdma_restrack_entry *res); +void rdma_restrack_abort_del (struct rdma_restrack_entry *res);void rdma_restrack_del (struct rdma_restrack_entry *res);void rdma_restrack_sync (struct rdma_restrack_entry *res); +void rdma_restrack_begin_del (struct rdma_restrack_entry *res); +void rdma_restrack_commit_del (struct rdma_restrack_entry *res);void rdma_restrack_new (struct rdma_restrack_entry *res,enum rdma_restrack_type type); void rdma_restrack_set_name(struct rdma_restrack_entry *res,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 841/1424 RDMA/core: Fix use after free in ib_query_qp()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Patrisious Haddad <[email protected]>
[ Upstream commit 709ba0e5311bd034eb4d9c1c00cc4e1109d6dc3e ]
When querying a QP via the netlink flow the only synchronization mechanism for the said QP is rdma_restrack_get(), meanwhile during the QP destroy path rdma_restrack_del() is called at the end of the ib_destroy_qp_user() function which is too late, since by then the vendor specific resources for said QP would already be destroyed, and till the rdma_restrack_del() is called this QP can still be accessed, which could cause the use after free below.
Fix this by moving the rdma_restrack_begin_del() to the start of the ib_destroy_qp_user(), which in turn waits for all usages of the QP to be done then removes it from the database to prevent access to it while it is being destroyed.
RIP: 0010:ib_query_qp+0x15/0x50 [ib_core] Code: 48 83 05 5d 8e b9 ff 01 eb b5 66 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 48 c7 46 40 00 00 00 00 48 c7 46 78 00 00 00 00 <48> 8b 07 48 8b 80 88 01 00 00 48 85 c0 74 1a 48 83 05 54 91 b9 ff RSP: 0018:ff11000108a8f2f0 EFLAGS: 00010202 RAX: 0000000000000000 RBX: ff11000108a8f370 RCX: ff11000108a8f370 RDX: 0000000000000000 RSI: ff11000108a8f3d8 RDI: 0000000000000000 RBP: ff1100010de5a000 R08: 0000000000000e80 R09: 0000000000000004 R10: ff110001057a604c R11: 0000000000000000 R12: ff11000108a8f370 R13: ff110001090e8000 R14: 0000000000000000 R15: ff110001057a602c FS: 00007f2ffd8db6c0(0000) GS:ff110008dc90b000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000000000000 CR3: 000000010b9a7004 CR4: 0000000000373eb0 Call Trace: <TASK> mlx5_ib_gsi_query_qp+0x21/0x50 [mlx5_ib] mlx5_ib_query_qp+0x689/0x9d0 [mlx5_ib] ib_query_qp+0x35/0x50 [ib_core] fill_res_qp_entry_query.isra.0+0x47/0x280 [ib_core] ? __wake_up+0x40/0x50 ? netlink_broadcast_filtered+0x15a/0x550 ? kobject_uevent_env+0x562/0x710 ? ep_poll_callback+0x242/0x270 ? __nla_put+0xc/0x20 ? nla_put+0x28/0x40 ? nla_put_string+0x2e/0x40 [ib_core] fill_res_qp_entry+0x138/0x190 [ib_core] res_get_common_dumpit+0x4a5/0x800 [ib_core] ? fill_res_qp_entry_query.isra.0+0x280/0x280 [ib_core] nldev_res_get_qp_dumpit+0x1e/0x30 [ib_core] netlink_dump+0x16f/0x450 __netlink_dump_start+0x1ce/0x2e0 rdma_nl_rcv_msg+0x1d3/0x330 [ib_core] ? nldev_res_get_qp_raw_dumpit+0x30/0x30 [ib_core] rdma_nl_rcv_skb.constprop.0.isra.0+0x108/0x180 [ib_core] rdma_nl_rcv+0x12/0x20 [ib_core] netlink_unicast+0x255/0x380 ? __alloc_skb+0xfa/0x1e0 netlink_sendmsg+0x1f3/0x420 __sock_sendmsg+0x38/0x60 ____sys_sendmsg+0x1e8/0x230 ? copy_msghdr_from_user+0xea/0x170 ___sys_sendmsg+0x7c/0xb0 ? __futex_wait+0x95/0xf0 ? __futex_wake_mark+0x40/0x40 ? futex_wait+0x67/0x100 ? futex_wake+0xac/0x1b0 __sys_sendmsg+0x5f/0xb0 do_syscall_64+0x55/0xb90 entry_SYSCALL_64_after_hwframe+0x4b/0x53
--- drivers/infiniband/core/verbs.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/infiniband/core/verbs.c +4 -1
@@ -2086,6 +2086,8 @@ int ib_destroy_qp_user(struct ib_qp *qp, struct ib_udata *udata)if (qp->real_qp != qp)return __ib_destroy_shared_qp (qp); +rdma_restrack_begin_del (&qp->res); + sec = qp->qp_sec;if (sec)ib_destroy_qp_security_begin (sec);
@@ -2098,6 +2100,7 @@ int ib_destroy_qp_user(struct ib_qp *qp, struct ib_udata *udata)if (ret) {if (sec)ib_destroy_qp_security_abort (sec); +rdma_restrack_abort_del (&qp->res);return ret; }
@@ -2110,7 +2113,7 @@ int ib_destroy_qp_user(struct ib_qp *qp, struct ib_udata *udata)if (sec)ib_destroy_qp_security_end (sec); -rdma_restrack_del (&qp->res); +rdma_restrack_commit_del (&qp->res);kfree (qp);return ret; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 842/1424 RDMA/core: Fix potential use after free in ib_destroy_cq_user()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Patrisious Haddad <[email protected]>
[ Upstream commit 3481bec4dfc4aee24ffea5a547ee95b70b67d9d5 ]
When accessing a CQ via the netlink path the only synchronization mechanism for the said CQ is rdma_restrack_get(). Currently, rdma_restrack_del() is invoked at the end of ib_destroy_cq_user(), which is too late, since by that point vendor-specific resources associated with the CQ might already be freed. This can leave a short window where the CQ remains accessible through restrack, leading to a potential use-after-free.
Fix this by moving the rdma_restrack_begin_del() call to the start of ib_destroy_cq_user(), ensuring that the CQ is removed from restrack before its internal resources are released. This guarantees that no new users hold references to a CQ that is in the process of destruction.
In addition, this change preserves the intended inverted order between create and destroy routines: resources are added to restrack at the end of successful creation, and hence shall be removed from the restrack first thing during the destruction flow, which keeps the lifecycle management consistent and predictable.
--- drivers/infiniband/core/verbs.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
drivers/infiniband/core/verbs.c +6 -2
@@ -2178,11 +2178,15 @@ int ib_destroy_cq_user(struct ib_cq *cq, struct ib_udata *udata)if (atomic_read (&cq->usecnt))return -EBUSY ; +rdma_restrack_begin_del (&cq->res); + ret = cq->device->ops.destroy_cq (cq, udata); -if (ret) +if (ret) { +rdma_restrack_abort_del (&cq->res);return ret; + } -rdma_restrack_del (&cq->res); +rdma_restrack_commit_del (&cq->res);kfree (cq);return ret; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 843/1424 RDMA/core: Fix potential use after free in ib_destroy_srq_user()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Patrisious Haddad <[email protected]>
[ Upstream commit 88244ecc71cc0b3ed200f5ef7ddea6686adfd730 ]
When accessing a SRQ via the netlink path the only synchronization mechanism for the said SRQ is rdma_restrack_get(). Currently, rdma_restrack_del() is invoked at the end of ib_destroy_srq_user(), which is too late, since by that point vendor-specific resources associated with the SRQ might already be freed. This can leave a short window where the SRQ remains accessible through restrack, leading to a potential use-after-free.
Fix this by moving the rdma_restrack_begin_del() call to the start of ib_destroy_srq_user(), ensuring that the SRQ is removed from restrack before its internal resources are released. This guarantees that no new users hold references to a SRQ that is in the process of destruction.
In addition, this change preserves the intended inverted order between create and destroy routines: resources are added to restrack at the end of successful creation, and hence shall be removed from the restrack first thing during the destruction flow, which keeps the lifecycle management consistent and predictable.
--- drivers/infiniband/core/verbs.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
drivers/infiniband/core/verbs.c +6 -2
@@ -1083,16 +1083,20 @@ int ib_destroy_srq_user(struct ib_srq *srq, struct ib_udata *udata)if (atomic_read (&srq->usecnt))return -EBUSY ; +rdma_restrack_begin_del (&srq->res); + ret = srq->device->ops.destroy_srq (srq, udata); -if (ret) +if (ret) { +rdma_restrack_abort_del (&srq->res);return ret; + }atomic_dec (&srq->pd->usecnt);if (srq->srq_type ==IB_SRQT_XRC && srq->ext.xrc.xrcd)atomic_dec (&srq->ext.xrc.xrcd->usecnt);if (ib_srq_has_cq (srq->srq_type))atomic_dec (&srq->ext.cq->usecnt); -rdma_restrack_del (&srq->res); +rdma_restrack_commit_del (&srq->res);kfree (srq);return ret;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 844/1424 RDMA/core: Fix potential use after free in counter_release()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Patrisious Haddad <[email protected]>
[ Upstream commit 235ef2d0e750885c29340b0fc40620a7a4f52e12 ]
When accessing a counter via the netlink path the only synchronization mechanism for the said counter is rdma_restrack_get(). Currently, rdma_restrack_del() is invoked at the end of counter_release(), which is too late, since by that point vendor-specific resources associated with the counter might already be freed. This can leave a short window where the counter remains accessible through restrack, leading to a potential use-after-free.
Fix this by moving the rdma_restrack_del() call to be before the freeing of the vendor-specific resources, ensuring that the counter is removed from restrack before its internal resources are released. This guarantees that no new users hold references to a counter that is in the process of destruction.
--- drivers/infiniband/core/counters.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/infiniband/core/counters.c +3 -2
@@ -217,7 +217,6 @@ static void rdma_counter_free(struct rdma_counter *counter)mutex_unlock (&port_counter->lock); -rdma_restrack_del (&counter->res);rdma_free_hw_stats_struct (counter->stats);kfree (counter); }
@@ -312,6 +311,7 @@ static void counter_release(struct kref *kref) counter = container_of(kref, struct rdma_counter, kref);counter_history_stat_update (counter); +rdma_restrack_del (&counter->res); counter->device->ops.counter_dealloc (counter);rdma_counter_free (counter); }
@@ -472,7 +472,8 @@ static struct rdma_counter *rdma_get_counter_by_id(struct ib_device *dev,return NULL ; counter = container_of(res, struct rdma_counter, res); -kref_get (&counter->kref); +if (!kref_get_unless_zero (&counter->kref)) + counter =NULL ;rdma_restrack_put (res);return counter;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 845/1424 RDMA/core: Add driver APIs pre_destroy_cq() and post_destroy_cq()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mark Zhang <[email protected]>
[ Upstream commit 5a2a5b65d5d67279be9e1f0e4b9baf39ee594cb1 ]
Currently in ib_free_cq, it disables IRQ or cancel the CQ work before driver destroy_cq. This isn't good as a new IRQ or a CQ work can be submitted immediately after disabling IRQ or canceling CQ work, which may run concurrently with destroy_cq and cause crashes.
The right flow should be:
1. Driver disables CQ to make sure no new CQ event will be submitted;
2. Disables IRQ or Cancels CQ work in core layer, to make sure no CQ
polling work is running;
3. Free all resources to destroy the CQ.
This patch adds 2 driver APIs:
- pre_destroy_cq(): Disable a CQ to prevent it from generating any new work completions, but not free any kernel resources;
- post_destroy_cq(): Free all kernel resources.
In ib_free_cq, the IRQ is disabled or CQ work is canceled after pre_destroy_cq, and before post_destroy_cq.
Stable-dep-of: 29dc2f8e1c97 ("RDMA/core: Fix potential use after free in ib_free_cq()")
--- drivers/infiniband/core/cq.c | 12 ++++++++++-- drivers/infiniband/core/device.c | 2 ++ include/rdma/ib_verbs.h | 9 +++++++++ 3 files changed, 21 insertions(+), 2 deletions(-)
drivers/infiniband/core/cq.c +10 -2
@@ -317,13 +317,18 @@ EXPORT_SYMBOL(__ib_alloc_cq_any);*/ void ib_free_cq (struct ib_cq *cq) { -int ret; +int ret =0 ;if (WARN_ON_ONCE (atomic_read (&cq->usecnt)))return ;if (WARN_ON_ONCE (cq->cqe_used))return ; +if (cq->device->ops.pre_destroy_cq) { + ret = cq->device->ops.pre_destroy_cq (cq); +WARN_ONCE (ret,"Disable of kernel CQ shouldn't fail" ); + } +switch (cq->poll_ctx) {case IB_POLL_DIRECT :break ;
@@ -340,7 +345,10 @@ void ib_free_cq(struct ib_cq *cq)rdma_dim_destroy (cq);trace_cq_free (cq); - ret = cq->device->ops.destroy_cq (cq,NULL ); +if (cq->device->ops.post_destroy_cq) + cq->device->ops.post_destroy_cq (cq); +else + ret = cq->device->ops.destroy_cq (cq,NULL );WARN_ONCE (ret,"Destroy of kernel CQ shouldn't fail" );rdma_restrack_del (&cq->res);kfree (cq->wc);
drivers/infiniband/core/device.c +2 -0
@@ -2730,8 +2730,10 @@ void ib_set_device_ops(struct ib_device *dev, const struct ib_device_ops *ops)SET_DEVICE_OP (dev_ops, modify_srq);SET_DEVICE_OP (dev_ops, modify_wq);SET_DEVICE_OP (dev_ops, peek_cq); +SET_DEVICE_OP (dev_ops, pre_destroy_cq);SET_DEVICE_OP (dev_ops, poll_cq);SET_DEVICE_OP (dev_ops, port_groups); +SET_DEVICE_OP (dev_ops, post_destroy_cq);SET_DEVICE_OP (dev_ops, post_recv);SET_DEVICE_OP (dev_ops, post_send);SET_DEVICE_OP (dev_ops, post_srq_recv);
include/rdma/ib_verbs.h +9 -0
@@ -2489,6 +2489,15 @@ struct ib_device_ops {int (*modify_cq)(struct ib_cq *cq,u16 cq_count,u16 cq_period);int (*destroy_cq)(struct ib_cq *cq,struct ib_udata *udata);int (*resize_cq)(struct ib_cq *cq,int cqe,struct ib_udata *udata); +/** +* pre_destroy_cq - Prevent a cq from generating any new work +* completions, but not free any kernel resources +*/ +int (*pre_destroy_cq)(struct ib_cq *cq); +/** +* post_destroy_cq - Free all kernel resources +*/ +void (*post_destroy_cq)(struct ib_cq *cq);struct ib_mr *(*get_dma_mr)(struct ib_pd *pd,int mr_access_flags); struct ib_mr *(*reg_user_mr)(struct ib_pd *pd, u64 start, u64 length, u64 virt_addr, int mr_access_flags,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 846/1424 RDMA/core: Fix potential use after free in ib_free_cq()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Patrisious Haddad <[email protected]>
[ Upstream commit 29dc2f8e1c97372c2871a70088707933515fbd5b ]
When accessing a CQ via the netlink path the only synchronization mechanism for the said CQ is rdma_restrack_get(). Currently, rdma_restrack_del() is invoked at the end of ib_free_cq(), which is too late, since by that point vendor-specific resources associated with the CQ might already be freed. This can leave a short window where the CQ remains accessible through restrack, leading to a potential use-after-free.
Fix this by moving the rdma_restrack_del() call to be before the freeing of the vendor-specific resources ensuring that the CQ is removed from restrack before its internal resources are released.
This guarantees that no new users hold references to a CQ that is in the process of destruction.
--- drivers/infiniband/core/cq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/infiniband/core/cq.c +1 -1
@@ -324,6 +324,7 @@ void ib_free_cq(struct ib_cq *cq)if (WARN_ON_ONCE (cq->cqe_used))return ; +rdma_restrack_del (&cq->res);if (cq->device->ops.pre_destroy_cq) { ret = cq->device->ops.pre_destroy_cq (cq);WARN_ONCE (ret,"Disable of kernel CQ shouldn't fail" );
@@ -350,7 +351,6 @@ void ib_free_cq(struct ib_cq *cq)else ret = cq->device->ops.destroy_cq (cq,NULL );WARN_ONCE (ret,"Destroy of kernel CQ shouldn't fail" ); -rdma_restrack_del (&cq->res);kfree (cq->wc);kfree (cq); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 847/1424 RDMA/core: Fix potential use after free in ib_dealloc_pd_user()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Patrisious Haddad <[email protected]>
[ Upstream commit 8b90e701342275f414e36e7421c502237df241ad ]
When accessing a PD via the netlink path the only synchronization mechanism for the said PD is rdma_restrack_get(). Currently, rdma_restrack_del() is invoked at the end of ib_dealloc_pd_user(), which is too late, since by that point vendor-specific resources associated with the PD might already be freed. This can leave a short window where the PD remains accessible through restrack, leading to a potential use-after-free.
Fix this by moving the rdma_restrack_begin_del() call to the start of ib_dealloc_pd_user(), ensuring that the PD is removed from restrack before its internal resources are released. This guarantees that no new users hold references to a PD that is in the process of destruction.
In addition, this change preserves the intended inverted order between create and destroy routines: resources are added to restrack at the end of successful creation, and hence shall be removed from the restrack first thing during the destruction flow, which keeps the lifecycle management consistent and predictable.
--- drivers/infiniband/core/verbs.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
drivers/infiniband/core/verbs.c +5 -2
@@ -335,6 +335,7 @@ int ib_dealloc_pd_user(struct ib_pd *pd, struct ib_udata *udata) {int ret; +rdma_restrack_begin_del (&pd->res);if (pd->__internal_mr) { ret = pd->device->ops.dereg_mr (pd->__internal_mr,NULL );WARN_ON (ret);
@@ -342,10 +343,12 @@ int ib_dealloc_pd_user(struct ib_pd *pd, struct ib_udata *udata) } ret = pd->device->ops.dealloc_pd (pd, udata); -if (ret) +if (ret) { +rdma_restrack_abort_del (&pd->res);return ret; + } -rdma_restrack_del (&pd->res); +rdma_restrack_commit_del (&pd->res);kfree (pd);return ret; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 848/1424 firmware: arm_scmi: Fix requested device removal race
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sudeep Holla <[email protected]>
[ Upstream commit 2c4097e6c4aed276c5e9ec2ab331ab397ea780bf ]
scmi_protocol_device_unrequest() drops scmi_requested_devices_mtx while notifying listeners but continues to retain the per-protocol list head. When two SCMI drivers for the same protocol unregister concurrently, one thread can remove the final request and free the list head while the other is running its notifier. The latter then dereferences the freed list head after reacquiring the mutex and can free it a second time.
Complete the list and IDR updates, including freeing an empty list head, before dropping the mutex. Keep the blocking notifier outside the critical section and retain only the detached request across the callback.
--- drivers/firmware/arm_scmi/bus.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-)
drivers/firmware/arm_scmi/bus.c +13 -13
@@ -146,6 +146,7 @@ static int scmi_protocol_device_request(const struct scmi_device_id *id_table)*/ static void scmi_protocol_device_unrequest (const struct scmi_device_id *id_table) { +struct scmi_requested_dev *rdev, *victim =NULL ;struct list_head *phead; pr_debug("Unrequesting SCMI device (%s) for protocol %x\n",
@@ -154,29 +155,28 @@ static void scmi_protocol_device_unrequest(const struct scmi_device_id *id_tablemutex_lock (&scmi_requested_devices_mtx); phead =idr_find (&scmi_requested_devices, id_table->protocol_id);if (phead) { -struct scmi_requested_dev *victim, *tmp; - -list_for_each_entry_safe (victim, tmp, phead, node) { -if (!strcmp (victim->id_table->name, id_table->name)) { -list_del (&victim->node); - -mutex_unlock (&scmi_requested_devices_mtx); -blocking_notifier_call_chain (&scmi_requested_devices_nh, -SCMI_BUS_NOTIFY_DEVICE_UNREQUEST , - (void *)victim->id_table); -kfree (victim); -mutex_lock (&scmi_requested_devices_mtx); +list_for_each_entry (rdev, phead, node) { +if (!strcmp (rdev->id_table->name, id_table->name)) { + victim = rdev; +list_del (&rdev->node);break ; } } -if (list_empty (phead)) { +if (victim &&list_empty (phead)) {idr_remove (&scmi_requested_devices, id_table->protocol_id);kfree (phead); } }mutex_unlock (&scmi_requested_devices_mtx); + +if (victim) { +blocking_notifier_call_chain (&scmi_requested_devices_nh, +SCMI_BUS_NOTIFY_DEVICE_UNREQUEST , + (void *)victim->id_table); +kfree (victim); + } } static const struct scmi_device_id *
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 849/1424 iommu/qcom: Remove sysfs device on probe failure path
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Haoxiang Li <[email protected]>
[ Upstream commit c579f18e79599c16168925cb149e1db3f29eea5f ]
In qcom_iommu_device_probe(), if iommu_device_register() fails, the sysfs device created by iommu_device_sysfs_add() is not released. Add a goto label to do the cleanup.
--- drivers/iommu/arm/arm-smmu/qcom_iommu.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/iommu/arm/arm-smmu/qcom_iommu.c +3 -1
@@ -832,7 +832,7 @@ static int qcom_iommu_device_probe(struct platform_device *pdev) ret =iommu_device_register (&qcom_iommu->iommu, &qcom_iommu_ops, dev);if (ret) {dev_err (dev,"Failed to register iommu\n" ); - goto err_pm_disable; + goto err_sysfs_remove; }if (qcom_iommu->local_base) {
@@ -843,6 +843,8 @@ static int qcom_iommu_device_probe(struct platform_device *pdev)return 0 ; +err_sysfs_remove: +iommu_device_sysfs_remove (&qcom_iommu->iommu); err_pm_disable:pm_runtime_disable (dev);return ret;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 850/1424 iommu/qcom: Fix inverted fault report check in qcom_iommu_fault()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mukesh Ojha <[email protected]>
[ Upstream commit 1f33b8208a1978b0c0d6ad60a47fe4bb7a235e58 ]
report_iommu_fault() returns 0 when a fault handler successfully handles the fault, and -ENOSYS when no handler is installed. The condition '!report_iommu_fault()' evaluates to true (printing "Unhandled context fault") precisely when the fault *was* handled, and stays silent when no handler is present — the opposite of what is intended.
Remove the '!' so the driver logs unhandled faults correctly.
--- drivers/iommu/arm/arm-smmu/qcom_iommu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/iommu/arm/arm-smmu/qcom_iommu.c +1 -1
@@ -210,7 +210,7 @@ static irqreturn_t qcom_iommu_fault(int irq, void *dev) fsynr =iommu_readl (ctx,ARM_SMMU_CB_FSYNR0 ); iova =iommu_readq (ctx,ARM_SMMU_CB_FAR ); -if (!report_iommu_fault (ctx->domain, ctx->dev, iova,0 )) { +if (report_iommu_fault (ctx->domain, ctx->dev, iova,0 )) { dev_err_ratelimited(ctx->dev, "Unhandled context fault: fsr=0x%x, " "iova=0x%016llx, fsynr=0x%x, cb=%d\n",
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 851/1424 thermal: intel: int3400: clean up ODVP on probe failures
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pengpeng Hou <[email protected]>
[ Upstream commit d83dc9ce57a746a6dca28439bcc0575d26fa6986 ]
evaluate_odvp() creates per-ODVP sysfs files before the thermal zone and later probe resources are registered. The current unwind path only calls cleanup_odvp() from the late sysfs failure path, so failures after evaluate_odvp() but before that label, including thermal_tripless_zone_device_register() failures, leave the ODVP files and storage behind.
Move the ODVP cleanup to the common ART/TRT unwind path so every failure after evaluate_odvp() releases the ODVP state. Also clear the cached ODVP pointers in cleanup_odvp(), because evaluate_odvp() can already call it for partial setup failures while probe continues.
--- drivers/thermal/intel/int340x_thermal/int3400_thermal.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/thermal/intel/int340x_thermal/int3400_thermal.c +3 -1
@@ -370,8 +370,10 @@ static void cleanup_odvp(struct int3400_thermal_priv *priv)kfree (priv->odvp_attrs[i].attr.attr.name); }kfree (priv->odvp_attrs); + priv->odvp_attrs =NULL ; }kfree (priv->odvp); + priv->odvp =NULL ; priv->odvp_count =0 ; }
@@ -653,7 +655,6 @@ static int int3400_thermal_probe(struct platform_device *pdev)acpi_remove_notify_handler (priv->adev->handle,ACPI_DEVICE_NOTIFY , int3400_notify); free_sysfs: -cleanup_odvp (priv);if (!ZERO_OR_NULL_PTR (priv->data_vault)) {sysfs_remove_group (&pdev->dev.kobj, &data_attribute_group);kfree (priv->data_vault);
@@ -667,6 +668,7 @@ static int int3400_thermal_probe(struct platform_device *pdev)acpi_thermal_rel_misc_device_remove (priv->adev->handle);thermal_zone_device_unregister (priv->thermal); free_art_trt: +cleanup_odvp (priv);kfree (priv->trts);kfree (priv->arts); free_priv:
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 852/1424 ext4: clear stale xarray tags on folios skipped during writeback
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gerald Yang <[email protected]>
[ Upstream commit ec524aae479b4b2078c47492b90ec21200bce434 ]
In data=journal mode, the writeback thread can hit the WARN_ON_ONCE(sb_rdonly(sb)) in ext4_journal_check_start() while the superblock is being remounted read-only during reboot:
Workqueue: writeback wb_workfn (flush-253:0) RIP: 0010:ext4_journal_check_start+0x8b/0xd0 Call Trace: __ext4_journal_start_sb+0x3c/0x1e0 mpage_prepare_extent_to_map+0x4af/0x580 ext4_do_writepages+0x3c0/0x1080 ext4_writepages+0xc8/0x1a0 do_writepages+0xc4/0x180 __writeback_single_inode+0x45/0x2f0 writeback_sb_inodes+0x26b/0x5d0 __writeback_inodes_wb+0x54/0x100 wb_writeback+0x1ac/0x320 wb_workfn+0x394/0x470
And followed by the warning:
EXT4-fs warning (device vda1): ext4_evict_inode:195: inode #6263:
comm (sd-umount): data will be lost
This issue is not reproduced every time, but frequently.
The reproduction step is to create a VM with 8 CPUs, 16G memory and setup data=journal:
sudo tune2fs -o journal_data /dev/vda1
Run fio:
rm -f fiotest
fio --name=fiotest --rw=randwrite --bs=4k --runtime=6 --ioengine=libaio --iodepth=256 --numjobs=8 --filename=fiotest --filesize=30G --group_reporting
Reboot the VM, and check the console output from:
virsh console testvm
But there is no dirty inode, folio_clear_dirty_for_io clears PG_dirty but leaves tags PAGECACHE_TAG_DIRTY and PAGECACHE_TAG_TOWRITE set which are only cleared by __folio_start_writeback.
In data=journal mode, jbd2 checkpoints the journalled data to its final location and clears its own dirty flag without touching folio PG_dirty or xarray dirty flags.
The commit f4a2b42e7891 ("ext4: fix stale xarray tags after writeback") fixes when PG_dirty is still set but there is no dirty page. Another case is PG_dirty is cleared, but PAGECACHE_TAG_DIRTY and PAGECACHE_TAG_TOWRITE is still set. In this case, writeback thread checks clean folio and skips it in mpage_prepare_extent_to_map:
if (!folio_test_dirty(folio) ||
...
folio_unlcok(folio);
continueAnd never reaches ext4_bio_write_folio where the commit f4a2b42e7891 clears the stale xarray tags. Print debug logs after the filesystem is remounted read-only:
writepages RDONLY nrpages=2048 dirtytag=1 wbtag=0 towrite=1 sync=0 And all folios are actually clean:
folio idx=3 dirty=0 wb=0 checked=0 dirtybuf=0 jbddirty=0 mapped=1
...
We need to clear the xarray stale tags for such clean folios by cycling them through writeback in the skip path, the same way f4a2b42e7891 does in ext4_bio_write_folio.
--- fs/ext4/inode.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-)
fs/ext4/inode.c +15 -3
@@ -2471,13 +2471,25 @@ static int mpage_prepare_extent_to_map(struct mpage_da_data *mpd)* page is already under writeback and we are not doing * a data integrity writeback, skip the page */ -if (!folio_test_dirty (folio) || - (folio_test_writeback (folio) && - (mpd->wbc->sync_mode ==WB_SYNC_NONE )) || +if ((folio_test_writeback (folio) && + mpd->wbc->sync_mode ==WB_SYNC_NONE ) ||unlikely (folio->mapping != mapping)) {folio_unlock (folio);continue ; } +/* +* If the folio is clean, skip writing it back. +* Cycle the folio through the writeback state +* though, to clear stale xarray tags. +*/ +if (!folio_test_dirty (folio)) { +if (!folio_test_writeback (folio)) { +__folio_start_writeback (folio, false); +folio_end_writeback (folio); + } +folio_unlock (folio); +continue ; + }folio_wait_writeback (folio);BUG_ON (folio_test_writeback (folio));
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 853/1424 ext4: drain in-flight DIO before buffered write fallback
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Baokun Li <[email protected]>
[ Upstream commit 15cdefd0c0522f9d5e12d947fa04f4c11649b699 ]
generic/746 started failing intermittently on ext3 (no-extent inodes). The test triggers 'Page cache invalidation failure on direct I/O' warnings and subsequent fsync returns -EIO. Adding a 50ms delay between ext4_buffered_write_iter() and filemap_write_and_wait_range() in ext4_dio_write_iter() makes the race almost always reproducible.
On no-extent inodes, DIO writes to holes cannot use unwritten extents, so ext4_iomap_alloc() leaves m_flags=0 and ext4_map_blocks() returns 0. The iomap layer then returns -ENOTBLK, causing fallback to buffered I/O.
The fallback path in ext4_dio_write_iter() calls ext4_buffered_write_iter() which dirties pages, then does flush and invalidate. However, there's an unprotected window between ext4_buffered_write_iter() returning (with inode lock released) and the subsequent flush+invalidate.
Concurrent async DIO completions from other threads can run kiocb_invalidate_post_direct_write() during this window. If pages have been re-dirtied, post-invalidation finds dirty pages and triggers the warning, setting -EIO in the error sequence.
Consider a file with two 4k extents: [hole][written]. Thread A does DIO to the written extent, while thread B does DIO spanning both:
kworker A (4k DIO, allocated block) kworker B (8k DIO, fallback)
----------------------------------- ----------------------------
inode_lock_shared() inode_lock_shared()
iomap_dio_rw(): iomap_dio_rw():
kiocb_invalidate_pages -> clean iomap_begin -> -ENOTBLK
submit_bio (async) dio->size = 0 inode_unlock_shared() inode_unlock_shared()
[bio pending in block layer] /* fallback: lock released */
ext4_buffered_write_iter()
inode_lock(exclusive)
generic_perform_write()
-> dirty pages [0, 8k]
inode_unlock(exclusive)
/* pages dirty, no lock */
[bio completes] filemap_write_and_wait_range()
iomap_dio_complete() -> flush dirty pages
kiocb_invalidate_post_direct_write() invalidate_mapping_pages()
invalidate_inode_pages2_range()
-> finds dirty page!
-> dio_warn_stale_pagecache()
-> errseq_set(-EIO)This issue can be triggered through normal I/O paths, not just intentionally overlapping DIO writes from userspace. For example, generic/746 uses a loop device where multiple kworkers issue concurrent I/O to the backing file. Additionally, when block_size < folio_size, non-overlapping DIO writes that share a large folio can also trigger the race.
Add inode_dio_wait() in ext4_buffered_write_iter() before ext4_write_checks() to drain all in-flight DIO. This ensures that all DIO clears existing pages before submitting IO (via kiocb_invalidate_pages()), all BIO waits for all DIO to complete (via inode_dio_wait()), and ext4_write_checks() observes the inode size after all completed DIO so that ext4_block_zero_eof() does not race with in-flight DIO, thus eliminating the race.
--- fs/ext4/file.c | 7 +++++++ 1 file changed, 7 insertions(+)
fs/ext4/file.c +7 -0
@@ -292,6 +292,13 @@ static ssize_t ext4_buffered_write_iter(struct kiocb *iocb,return -EOPNOTSUPP ;inode_lock (inode); + +/* +* Prevent concurrent direct I/O and buffered I/O to the same file +* range. Wait for in-flight DIO to finish before dirtying pages. +*/ +inode_dio_wait (inode); + ret =ext4_write_checks (iocb, from);if (ret <=0 ) goto out;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 854/1424 wifi: ath6kl: avoid buffer overreads in WMI event handlers
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jeff Johnson <[email protected]>
[ Upstream commit f57314aade9d74d30f3360ec5ef85a83654748be ]
The following WMI event handlers currently read from the event buffer without first verifying that the message was large enough to hold the expected event:ath6kl_wmi_scan_complete_rx() ath6kl_wmi_addba_req_event_rx() ath6kl_wmi_delba_req_event_rx()
Add length checks to prevent overread.
--- drivers/net/wireless/ath/ath6kl/wmi.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-)
drivers/net/wireless/ath/ath6kl/wmi.c +15 -2
@@ -1296,6 +1296,9 @@ static int ath6kl_wmi_scan_complete_rx(struct wmi *wmi, u8 *datap, int len, {struct wmi_scan_complete_event *ev; +if (len <sizeof (*ev)) +return -EINVAL ; + ev = (struct wmi_scan_complete_event *) datap;ath6kl_scan_complete_evt (vif,a_sle32_to_cpu (ev->status));
@@ -3372,7 +3375,12 @@ static int ath6kl_wmi_get_pmkid_list_event_rx(struct wmi *wmi, u8 *datap,static int ath6kl_wmi_addba_req_event_rx (struct wmi *wmi,u8 *datap,int len,struct ath6kl_vif *vif) { -struct wmi_addba_req_event *cmd = (struct wmi_addba_req_event *) datap; +struct wmi_addba_req_event *cmd; + +if (len <sizeof (*cmd)) +return -EINVAL ; + + cmd = (struct wmi_addba_req_event *)datap;aggr_recv_addba_req_evt (vif, cmd->tid,le16_to_cpu (cmd->st_seq_no), cmd->win_sz);
@@ -3383,7 +3391,12 @@ static int ath6kl_wmi_addba_req_event_rx(struct wmi *wmi, u8 *datap, int len,static int ath6kl_wmi_delba_req_event_rx (struct wmi *wmi,u8 *datap,int len,struct ath6kl_vif *vif) { -struct wmi_delba_event *cmd = (struct wmi_delba_event *) datap; +struct wmi_delba_event *cmd; + +if (len <sizeof (*cmd)) +return -EINVAL ; + + cmd = (struct wmi_delba_event *)datap;aggr_recv_delba_req_evt (vif, cmd->tid);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 855/1424 wifi: ath12k: Correctly copy the hint BSSID in WMI scan request
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jeff Johnson <[email protected]>
[ Upstream commit 7b0bd40e97a00991122122d5888ae455fb2bfc7a ]
Currently, in ath12k_wmi_send_scan_start_cmd(), the logic to populate the hint_bssid copies the BSSID in the wrong direction, from the firmware message to the argument buffer. Swap the parameters so that the BSSID is correctly populated in the firmware message from the argument buffer.
Compile tested only.
--- drivers/net/wireless/ath/ath12k/wmi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/net/wireless/ath/ath12k/wmi.c +2 -2
@@ -2388,8 +2388,8 @@ int ath12k_wmi_send_scan_start_cmd(struct ath12k *ar,for (i =0 ; i < arg->num_hint_bssid; ++i) { hint_bssid->freq_flags = arg->hint_bssid[i].freq_flags; -ether_addr_copy (&arg->hint_bssid[i].bssid.addr[0 ], - &hint_bssid->bssid.addr[0 ]); +ether_addr_copy (&hint_bssid->bssid.addr[0 ], + &arg->hint_bssid[i].bssid.addr[0 ]); hint_bssid++; } }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 856/1424 wifi: ath11k: Correctly copy the hint BSSID in WMI scan request
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jeff Johnson <[email protected]>
[ Upstream commit 6fe2dddf59bbb2a96be0fcf23a205807b25ac173 ]
Currently, in ath11k_wmi_send_scan_start_cmd(), the logic to populate the hint_bssid copies the BSSID in the wrong direction, from the firmware message to the argument buffer. Swap the parameters so that the BSSID is correctly populated in the firmware message from the argument buffer.
This issue was reported on ath12k, but exists in ath11k as well.
Compile tested only.
--- drivers/net/wireless/ath/ath11k/wmi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/net/wireless/ath/ath11k/wmi.c +2 -2
@@ -2364,8 +2364,8 @@ int ath11k_wmi_send_scan_start_cmd(struct ath11k *ar,for (i =0 ; i < params->num_hint_bssid; ++i) { hint_bssid->freq_flags = params->hint_bssid[i].freq_flags; -ether_addr_copy (¶ms->hint_bssid[i].bssid.addr[0 ], - &hint_bssid->bssid.addr[0 ]); +ether_addr_copy (&hint_bssid->bssid.addr[0 ], + ¶ms->hint_bssid[i].bssid.addr[0 ]); hint_bssid++; } }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 857/1424 wifi: ath12k: Avoid buffer overread in ath12k_wmi_op_rx()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jeff Johnson <[email protected]>
[ Upstream commit 7698656a2f7b045af5a6859766238cefea1b1945 ]
Currently, in ath12k_wmi_op_rx(), the firmware buffer is read without first verifying that the buffer has enough data to hold a header. This could result in a buffer overread.
Update the logic to verify the buffer contains at least enough data to hold a wmi_cmd_hdr before reading from the buffer.
Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c7-00108-QCAHMTSWPL_V1.0_V2.0_SILICONZ_UPSTREAM-3
--- drivers/net/wireless/ath/ath12k/wmi.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/net/wireless/ath/ath12k/wmi.c +4 -4
@@ -6652,12 +6652,12 @@ static void ath12k_wmi_op_rx(struct ath12k_base *ab, struct sk_buff *skb)struct wmi_cmd_hdr *cmd_hdr;enum wmi_tlv_event_id id; - cmd_hdr = (struct wmi_cmd_hdr *)skb->data; - id =le32_get_bits (cmd_hdr->cmd_id,WMI_CMD_HDR_CMD_ID ); - -if (!skb_pull (skb,sizeof (struct wmi_cmd_hdr ))) + cmd_hdr =skb_pull_data (skb,sizeof (*cmd_hdr)); +if (!cmd_hdr) goto out; + id =le32_get_bits (cmd_hdr->cmd_id,WMI_CMD_HDR_CMD_ID ); +switch (id) {/* Process all the WMI events here */ case WMI_SERVICE_READY_EVENTID :
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 858/1424 wifi: ath11k: Avoid buffer overread in ath11k_wmi_tlv_op_rx()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jeff Johnson <[email protected]>
[ Upstream commit 9ef9dd30058cc9223c72f711dca1a28a5947d0c5 ]
Currently, in ath11k_wmi_tlv_op_rx(), the firmware buffer is read without first verifying that the buffer has enough data to hold a header. This could result in a buffer overread.
Add an upfront length check before dereferencing skb->data as a wmi_cmd_hdr. The check is placed before the trace_ath11k_wmi_event() call to preserve the existing trace semantics (tracing the full raw WMI event including the header), unlike the analogous ath12k fix which could use skb_pull_data() directly.
Compile tested only.
--- drivers/net/wireless/ath/ath11k/wmi.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/net/wireless/ath/ath11k/wmi.c +4 -2
@@ -8659,13 +8659,15 @@ static void ath11k_wmi_tlv_op_rx(struct ath11k_base *ab, struct sk_buff *skb)struct wmi_cmd_hdr *cmd_hdr;enum wmi_tlv_event_id id; +if (skb->len <sizeof (*cmd_hdr)) + goto out; + cmd_hdr = (struct wmi_cmd_hdr *)skb->data; id =FIELD_GET (WMI_CMD_HDR_CMD_ID , (cmd_hdr->cmd_id));trace_ath11k_wmi_event (ab, id, skb->data, skb->len); -if (skb_pull (skb,sizeof (struct wmi_cmd_hdr )) ==NULL ) - goto out; +skb_pull (skb,sizeof (*cmd_hdr));switch (id) {/* Process all the WMI events here */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 859/1424 RDMA/bnxt_re: Clear VM_MAYWRITE on DBR/toggle page mmap
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Selvin Xavier <[email protected]>
[ Upstream commit 9b66c9af7172ffcf727214fa0ebe9a5e1ed6eb16 ]
bnxt_re_mmap() rejects VM_WRITE for the DBR_PAGE and TOGGLE_PAGE mmap flags, but a read-only mapping can still retain VM_MAYWRITE. nd later be upgraded with mprotect(PROT_WRITE). This can bypass the write check that only runs at mmap time.
Clear VM_MAYWRITE before vm_insert_page() in the shared DBR/toggle-page branch, matching the existing policy that userspace writes are not expected for these pages.
--- drivers/infiniband/hw/bnxt_re/ib_verbs.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/infiniband/hw/bnxt_re/ib_verbs.c +4 -2
@@ -4268,11 +4268,13 @@ int bnxt_re_mmap(struct ib_ucontext *ib_uctx, struct vm_area_struct *vma)break ;case BNXT_RE_MMAP_DBR_PAGE :/* Driver doesn't expect write access for user space */ -if (vma->vm_flags &VM_WRITE ) +if (vma->vm_flags &VM_WRITE ) { ret = -EFAULT ; -else + }else { +vm_flags_clear (vma,VM_MAYWRITE ); ret =vm_insert_page (vma, vma->vm_start,virt_to_page ((void *)bnxt_entry->mem_offset)); + }break ;default : ret = -EINVAL ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 860/1424 ext4: fix buffer_head leak in ext4_init_orphan_info
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guanghui Yang <[email protected]>
[ Upstream commit 05704335803b69c1bfa8637b7ada942bf2ee8a41 ]
ext4_init_orphan_info() reads orphan file blocks with ext4_bread() and stores the returned buffer_head in oi->of_binfo[i].ob_bh.
If ext4_bread() succeeds but the orphan block magic or checksum validation fails, the function jumps to out_free. However, the old out_free loop starts releasing buffers from i - 1, so the current buffer_head at index i is skipped.
This leaks the buffer_head reference obtained by ext4_bread() on the bad magic and bad checksum error paths.
Fix this by tracking the number of successfully read buffer_heads and releasing exactly those buffer_heads on the error path.
--- fs/ext4/orphan.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
fs/ext4/orphan.c +6 -2
@@ -573,6 +573,7 @@ int ext4_init_orphan_info(struct super_block *sb)int i, j;int ret;int free; +int loaded =0 ;__le32 *bdata;int inodes_per_ob =ext4_inodes_per_orphan_block (sb);struct ext4_orphan_block_tail *ot;
@@ -616,6 +617,7 @@ int ext4_init_orphan_info(struct super_block *sb) ret = -EIO ; goto out_free; } + loaded++; ot =ext4_orphan_block_tail (sb, oi->of_binfo[i].ob_bh);if (le32_to_cpu (ot->ob_magic) !=EXT4_ORPHAN_BLOCK_MAGIC ) {ext4_error (sb,"orphan file block %d: bad magic" , i);
@@ -638,8 +640,10 @@ int ext4_init_orphan_info(struct super_block *sb)iput (inode);return 0 ; out_free: -for (i--; i >=0 ; i--) -brelse (oi->of_binfo[i].ob_bh); +while (loaded >0 ) { + loaded--; +brelse (oi->of_binfo[loaded].ob_bh); + }kvfree (oi->of_binfo); out_put:iput (inode);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 861/1424 ext4: check dir entry fits before reading the hash trailer in ext4_search_dir()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xiang Mei <[email protected]>
[ Upstream commit c7e6b863d298f56522d0d08554bbea7f142e6588 ]
For casefolded encrypted directories ext4 stores an 8-byte hash trailer after the name (EXT4_DIRENT_HASHES()), at an offset derived from de->name_len. On the sb_no_casefold_compat_fallback() path ext4_match() reads that trailer, but ext4_search_dir()'s by-hand pre-check only tests de->name + de->name_len <= dlimit, which proves the name fits, not the rounded trailer. A crafted entry whose name ends at the block boundary passes the check while EXT4_DIRENT_HASHES(de) lands past the block end, so ext4_match() reads out of bounds on an ordinary lookup. KASAN reports it as a use-after-free when the page after the directory block holds a freed object:
BUG: KASAN: use-after-free in ext4_match (fs/ext4/namei.c:1435) Read of size 4 at addr ffff888010458000 by task exploit Call Trace: ext4_match (fs/ext4/namei.c:1435) ext4_search_dir (fs/ext4/namei.c:1470) __ext4_find_entry (fs/ext4/namei.c:1268 fs/ext4/namei.c:1632) ext4_lookup (fs/ext4/namei.c:1703 fs/ext4/namei.c:1769) ... filename_lookup (fs/namei.c:2842) vfs_statx (fs/stat.c:353) __do_sys_newfstatat (fs/stat.c:538) do_syscall_64 (arch/x86/entry/syscall_64.c:94) entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121)
Require, for hash-in-dirent directories, that the whole entry including the rounded trailer fits before calling ext4_match(). This is the same bound ext4_check_dir_entry() already enforces via ext4_dir_rec_len(), so no well-formed entry is rejected. The other caller, ext4_find_dest_de(), runs ext4_check_dir_entry() first and is unaffected.
--- fs/ext4/namei.c | 2 ++ 1 file changed, 2 insertions(+)
fs/ext4/namei.c +2 -0
@@ -1542,6 +1542,8 @@ int ext4_search_dir(struct buffer_head *bh, char *search_buf, int buf_size,/* this code is executed quadratically often */ /* do minimal checking `by hand' */ if (de->name + de->name_len <= dlimit && + (!ext4_hash_in_dirent (dir) || + (char *)de +ext4_dir_rec_len (de->name_len, dir) <= dlimit) &&ext4_match (dir, fname, de)) {/* found a match - just to be sure, do * a full check */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 862/1424 ARM: dts: allwinner: a10: Fix PMU interrupt
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andre Przywara <[email protected]>
[ Upstream commit eb7051f756460d7b951e94d9656e31ebb631ba28 ]
The Performance Monitoring Unit of the Cortex-A8 cores in the Allwinner A10 SoC is connected to interrupt line 66, not 3. This is shown in the manual (where interrupt 3 is assigned to UART2, also in our .dtsi), but has also been confirmed by triggering an PMU overflow interrupt and inspecting the IRQ controller status registers (from U-Boot). Please note that "perf stat" does not use interrupts, this might explain why this evaded the initial testing.
--- arch/arm/boot/dts/allwinner/sun4i-a10.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm/boot/dts/allwinner/sun4i-a10.dtsi +1 -1
@@ -185,7 +185,7 @@ de: display-engine { pmu { compatible = "arm,cortex-a8-pmu"; - interrupts = <3>; + interrupts = <66>; }; reserved-memory {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 863/1424 firmware: arm_scmi: Add multiple protocols registration support
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cristian Marussi <[email protected]>
[ Upstream commit 2858f6e5f06440d6b9e9c3f57bc68915344830a9 ]
Add the capability for a SCMI driver to register to the core SCMI stack with multiple SCMI protocols. In such a case the SCMI driver probe function will end up being called once for each registered protocol which have been also found as implemented on the platform.
This is especially useful in testing scenarios.
Stable-dep-of: 9f7cd6a62aa7 ("firmware: arm_scmi: Unrequest devices if driver registration fails")
--- drivers/firmware/arm_scmi/bus.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-)
drivers/firmware/arm_scmi/bus.c +22 -2
@@ -134,6 +134,17 @@ static int scmi_protocol_device_request(const struct scmi_device_id *id_table)return ret; } +static int scmi_protocol_table_register (const struct scmi_device_id *id_table) +{ +int ret =0 ; +const struct scmi_device_id *entry; + +for (entry = id_table; entry->name && ret ==0 ; entry++) + ret =scmi_protocol_device_request (entry); + +return ret; +} +/** * scmi_protocol_device_unrequest - Helper to unrequest a device *
@@ -179,6 +190,15 @@ static void scmi_protocol_device_unrequest(const struct scmi_device_id *id_table } } +static void +scmi_protocol_table_unregister (const struct scmi_device_id *id_table) +{ +const struct scmi_device_id *entry; + +for (entry = id_table; entry->name; entry++) +scmi_protocol_device_unrequest (entry); +} +static const struct scmi_device_id *scmi_dev_match_id (struct scmi_device *scmi_dev,struct scmi_driver *scmi_drv) {
@@ -275,7 +295,7 @@ int scmi_driver_register(struct scmi_driver *driver, struct module *owner,if (!driver->probe)return -EINVAL ; - retval =scmi_protocol_device_request (driver->id_table); + retval =scmi_protocol_table_register (driver->id_table);if (retval)return retval;
@@ -295,7 +315,7 @@ EXPORT_SYMBOL_GPL(scmi_driver_register);void scmi_driver_unregister (struct scmi_driver *driver) {driver_unregister (&driver->driver); -scmi_protocol_device_unrequest (driver->id_table); +scmi_protocol_table_unregister (driver->id_table); }EXPORT_SYMBOL_GPL (scmi_driver_unregister);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 864/1424 firmware: arm_scmi: Unrequest devices if driver registration fails
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sudeep Holla <[email protected]>
[ Upstream commit 9f7cd6a62aa754ed6b48cbd5d50de40add1bcc86 ]
scmi_driver_register() requests protocol devices before registering the driver. If driver_register() fails, those requests remain in the global IDR and retain pointers to the module's ID table. Once the failed module load releases that storage, later request matching or SCMI device creation can dereference the stale pointers.
Unrequest the complete protocol table before returning the registration failure. At this point table registration succeeded, so every entry is owned by the current registration attempt.
--- drivers/firmware/arm_scmi/bus.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-)
drivers/firmware/arm_scmi/bus.c +7 -3
@@ -305,10 +305,14 @@ int scmi_driver_register(struct scmi_driver *driver, struct module *owner, driver->driver.mod_name = mod_name; retval =driver_register (&driver->driver); -if (!retval) -pr_debug ("Registered new scmi driver %s\n" , driver->name); +if (retval) { +scmi_protocol_table_unregister (driver->id_table); +return retval; + } -return retval; +pr_debug ("Registered new scmi driver %s\n" , driver->name); + +return 0 ; }EXPORT_SYMBOL_GPL (scmi_driver_register);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 865/1424 perf cs-etm: Flush thread stacks after decoder reset
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Leo Yan <[email protected]>
[ Upstream commit ea5075e3776846d4941dddf1549426ebd3feb81f ]
Perf resets the CoreSight decoder when moving to a new AUX trace buffer, this causes trace discontinunity globally.
For callchain synthesis, keeping thread-stack state after decoder reset can leave stale call/return history attached to threads that are decoded later, producing incorrect synthesized callchains.
Flush all host thread stacks after a decoder reset. When virtualization is present, flush the guest thread stacks as well.
Stable-dep-of: ec99be8a31db ("perf cs-etm: Avoid truncating AUX buffer sizes to int")
--- tools/perf/util/cs-etm.c | 45 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+)
tools/perf/util/cs-etm.c +45 -0
@@ -1946,6 +1946,45 @@ static int cs_etm__end_block(struct cs_etm_queue *etmq,return 0 ; } + +static int cs_etm__flush_stack_cb (struct thread *thread, +void *data__maybe_unused ) +{ +thread_stack__flush (thread); +return 0 ; +} + +static void cs_etm__flush_machine_stack (struct cs_etm_queue *etmq,pid_t pid) +{ +struct machine *machine; + + machine =machines__find (&etmq->etm->session->machines, pid); +if (machine) +machine__for_each_thread (machine, cs_etm__flush_stack_cb,NULL ); +} + +static void cs_etm__flush_all_stack (struct cs_etm_queue *etmq) +{ +enum cs_etm_pid_fmt pid_fmt =cs_etm__get_pid_fmt (etmq); + +if (!etmq->etm->synth_opts.last_branch) +return ; + +switch (pid_fmt) { +case CS_ETM_PIDFMT_CTXTID2 : +/* Clear the guest stack if virtualization is supported */ +cs_etm__flush_machine_stack (etmq,DEFAULT_GUEST_KERNEL_ID ); + fallthrough; +case CS_ETM_PIDFMT_CTXTID : +cs_etm__flush_machine_stack (etmq,HOST_KERNEL_ID ); +break ; +case CS_ETM_PIDFMT_NONE : +default : +break ; + + } +} +/* * cs_etm__get_data_block: Fetch a block from the auxtrace_buffer queue * if need be.
@@ -1968,6 +2007,12 @@ static int cs_etm__get_data_block(struct cs_etm_queue *etmq) ret =cs_etm_decoder__reset (etmq->decoder);if (ret)return ret; + +/* +* Since the decoder is reset, this causes a global trace +* discontinuity. Flush all thread stacks. +*/ +cs_etm__flush_all_stack (etmq); }return etmq->buf_len;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 866/1424 perf cs-etm: Avoid truncating AUX buffer sizes to int
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Leo Yan <[email protected]>
[ Upstream commit ec99be8a31db999a4f866be74ea7db61dbb19f24 ]
cs_etm__get_trace() returns an int, but it used to return etmq->buf_len on success. That value comes from auxtrace_buffer::size, which is a size_t. For a large AUX trace block, returning the byte count through an int can overflow and make a valid buffer look like a negative error.
The callers do not need the actual byte count from cs_etm__get_trace(). The buffer length is already stored in the etmq->buf_len. The callers only need to distinguish three states:
< 0: error
= 0: no more AUX buffers
Quoted 1 line
0: data is available
Make cs_etm__get_trace() return 0 for all non-error cases and use etmq->buf_len to indicate whether a new buffer was found. Then make cs_etm__get_data_block() return 1 whenever data is available, instead of returning the buffer length.
Also refactor cs_etm__get_data_block() to make its return value semantics clearer.
--- tools/perf/util/cs-etm.c | 46 +++++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 20 deletions(-)
tools/perf/util/cs-etm.c +26 -20
@@ -1362,8 +1362,7 @@ cs_etm__get_trace(struct cs_etm_queue *etmq) etmq->buf_used =0 ; etmq->buf_len = aux_buffer->size; etmq->buf = aux_buffer->data; - -return etmq->buf_len; +return 0 ; }/*
@@ -1996,26 +1995,33 @@ static int cs_etm__get_data_block(struct cs_etm_queue *etmq) {int ret; -if (!etmq->buf_len) { - ret =cs_etm__get_trace (etmq); -if (ret <=0 ) -return ret; -/* -* We cannot assume consecutive blocks in the data file -* are contiguous, reset the decoder to force re-sync. -*/ - ret =cs_etm_decoder__reset (etmq->decoder); -if (ret) -return ret; +/* The current block is not finished */ +if (etmq->buf_len) +return 1 ; -/* -* Since the decoder is reset, this causes a global trace -* discontinuity. Flush all thread stacks. -*/ -cs_etm__flush_all_stack (etmq); - } + ret =cs_etm__get_trace (etmq); +if (ret <0 ) +return ret; + +/* No more buffer to read */ +if (!etmq->buf_len) +return 0 ; + +/* +* We cannot assume consecutive blocks in the data file +* are contiguous, reset the decoder to force re-sync. +*/ + ret =cs_etm_decoder__reset (etmq->decoder); +if (ret) +return ret; + +/* +* Since the decoder is reset, this causes a global trace +* discontinuity. Flush all thread stacks. +*/ +cs_etm__flush_all_stack (etmq); -return etmq->buf_len; +return 1 ; } static bool cs_etm__is_svc_instr(struct cs_etm_queue *etmq,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 867/1424 xfrm: Fix skb double-free in xfrm_dev_direct_output()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sanghyun Park <[email protected]>
[ Upstream commit 2aed51fc58d9ce450e2c116efb956160fd06fa02 ]
A return value other than 1 from local_out() means that the skb has been consumed or its ownership was transferred. xfrm_dev_direct_output() nevertheless frees the skb on this path, causing a double-free when netfilter drops the packet and invalidating any other owner.
Return the local_out() result directly, matching the ownership handling in xfrm_output_resume().
--- net/xfrm/xfrm_output.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
net/xfrm/xfrm_output.c +1 -3
@@ -627,10 +627,8 @@ static int xfrm_dev_direct_output(struct sock *sk, struct xfrm_state *x,nf_reset_ct (skb); err =skb_dst (skb)->ops->local_out (net, sk, skb); -if (unlikely (err !=1 )) { -kfree_skb (skb); +if (unlikely (err !=1 ))return err; - }/* In transport mode, network destination is * directly reachable, while in tunnel mode,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 868/1424 PM: hibernate: Fix memory leak in snapshot_write_next() error path
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Malaya Kumar Rout <[email protected]>
[ Upstream commit 21d5c4cee31c5ce78f6decc7fafc7e7759af391f ]
When memory_bm_create() succeeds for copy_bm but fails for zero_bm, the function returns without freeing the resources allocated for copy_bm. This results in a memory leak that includes radix tree nodes, zone structures, and page lists.
Fix this by calling memory_bm_free() to release copy_bm's resources before returning the error code when zero_bm allocation fails.
--- kernel/power/snapshot.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
kernel/power/snapshot.c +3 -2
@@ -2808,9 +2808,10 @@ int snapshot_write_next(struct snapshot_handle *handle)return error; error =memory_bm_create (&zero_bm,GFP_ATOMIC ,PG_ANY ); -if (error) +if (error) { +memory_bm_free (©_bm,PG_UNSAFE_CLEAR );return error; - + } nr_zero_pages =0 ;hibernate_restore_protection_begin ();
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 869/1424 leds: pca9532: Fix phantom device registration on missing hardware
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cosmo Chou <[email protected]>
[ Upstream commit 8d6b6c05b8e33d11e3fb3203309385e1a9cceecd ]
The initial PWM and PSC register writes in pca9532_configure() do not check the return values of i2c_smbus_write_byte_data(). If the I2C device is physically absent from the bus, the write fails with -ENXIO. However, the driver ignores this error and allows probe() to complete successfully.
This results in the registration of phantom LED class devices and gpiochips backed by non-existent hardware. Subsequent GPIO reads from these phantom chips return bogus values (due to -ENXIO being truncated to an unsigned char in pca9532_gpio_get_value()), silently corrupting hardware state tracking in userspace.
Propagate the I2C write failures back to probe() so the driver core can gracefully abort binding and release devres-managed resources.
--- drivers/leds/leds-pca9532.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-)
drivers/leds/leds-pca9532.c +8 -4
@@ -353,10 +353,14 @@ static int pca9532_configure(struct i2c_client *client,for (i =0 ; i <2 ; i++) { data->pwm[i] = pdata->pwm[i]; data->psc[i] = pdata->psc[i]; -i2c_smbus_write_byte_data (client,PCA9532_REG_PWM (maxleds, i), - data->pwm[i]); -i2c_smbus_write_byte_data (client,PCA9532_REG_PSC (maxleds, i), - data->psc[i]); + err =i2c_smbus_write_byte_data (client,PCA9532_REG_PWM (maxleds, i), + data->pwm[i]); +if (err <0 ) +return err; + err =i2c_smbus_write_byte_data (client,PCA9532_REG_PSC (maxleds, i), + data->psc[i]); +if (err <0 ) +return err; }for (i =0 ; i < data->chip_info->num_leds; i++) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 870/1424 drm/tve200: add OF module alias for autoloading
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Can Peng <[email protected]>
[ Upstream commit b6c3585f2058e0fbfa8cb403458f5cc6cf5c5e06 ]
The TVE200 DRM driver can be built as a module and uses tve200_of_match as its OF match table, but the table is not exported for module alias generation.
Add the MODULE_DEVICE_TABLE(of, ...) entry so modpost can generate OF module aliases for OF based module autoloading.
--- drivers/gpu/drm/tve200/tve200_drv.c | 1 + 1 file changed, 1 insertion(+)
drivers/gpu/drm/tve200/tve200_drv.c +1 -0
@@ -261,6 +261,7 @@ static const struct of_device_id tve200_of_match[] = { }, {}, }; +MODULE_DEVICE_TABLE (of, tve200_of_match);static struct platform_driver tve200_driver = { .driver = {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 871/1424 netfilter: nf_nat_sip: rewind offset when NAT shrinks the packet
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Florian Westphal <[email protected]>
[ Upstream commit 16aecbe3036f6097c26b51b12e4c1cf207769690 ]
sashiko says:
If map_addr() changes the packet length, such as when the public NAT IP string is shorter or longer than the internal IP, coff will still point to the offset relative to the pre-mangled packet.
If the packet shrinks, coff could overshoot the correct position, potentially causing the next ct_sip_parse_header_uri() call to silently skip bytes and miss subsequent Contact headers. Could this lead to a failure to NAT those subsequent headers and leak internal network details?
--- net/netfilter/nf_nat_sip.c | 5 +++++ 1 file changed, 5 insertions(+)
net/netfilter/nf_nat_sip.c +5 -0
@@ -267,12 +267,17 @@ static unsigned int nf_nat_sip(struct sk_buff *skb, unsigned int protoff, SIP_HDR_CONTACT, &in_header, &matchoff, &matchlen, &addr, &port) > 0) { +int old_len = skb->len, delta; +if (!map_addr (skb, protoff, dataoff, dptr, datalen, matchoff, matchlen, &addr, port)) {nf_ct_helper_log (skb, ct,"cannot mangle contact" );return NF_DROP ; } + + delta = (int )skb->len - old_len; + coff += delta; } if (!map_sip_addr(skb, protoff, dataoff, dptr, datalen, SIP_HDR_FROM) ||
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 872/1424 fs/ntfs3: fix out-of-bounds read of INDEX_ROOT in reparse/objid init
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Weiming Wu <[email protected]>
[ Upstream commit 2064bc663f89e61b8681c1fb9d1ce445de72063d ]
ntfs_reparse_init() and ntfs_objid_init() parse the index root of the $Extend/$Reparse and $Extend/$ObjId metafiles (the INDEX_ROOT attributes named $R and $O). They read its type and rule fields through resident_data(), which does not check that the resident attribute is large enough to hold them.
mi_enum_attr() accepts a resident attribute with data_off == asize and data_size == 0. For such an attribute placed last in its MFT record, resident_data() returns a pointer to the end of the record_size buffer, so reading root->type / root->rule reads past the allocation.
Use resident_data_ex(attr, sizeof(struct INDEX_ROOT)) and bail out when it returns NULL, as ntfs_security_init() already does for $SDH / $SII.
The attribute is only parsed while mounting a crafted image, so this needs CAP_SYS_ADMIN.
BUG: KASAN: slab-out-of-bounds in ntfs_reparse_init (fs/ntfs3/fsntfs.c:2306) Read of size 4 at addr ffff88801219dc00 by task mount ntfs_reparse_init (fs/ntfs3/fsntfs.c:2306) ntfs_fill_super (fs/ntfs3/super.c:1604) get_tree_bdev_flags (fs/super.c:1703) vfs_get_tree (fs/super.c:1758) path_mount (fs/namespace.c:4131) __x64_sys_mount (fs/namespace.c:4360)
--- fs/ntfs3/fsntfs.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
fs/ntfs3/fsntfs.c +4 -4
@@ -2313,8 +2313,8 @@ int ntfs_reparse_init(struct ntfs_sb_info *sbi) goto out; } - root_r =resident_data (attr); -if (root_r->type !=ATTR_ZERO || + root_r =resident_data_ex (attr,sizeof (struct INDEX_ROOT )); +if (!root_r || root_r->type !=ATTR_ZERO || root_r->rule !=NTFS_COLLATION_TYPE_UINTS ) { err = -EINVAL ; goto out;
@@ -2351,8 +2351,8 @@ int ntfs_objid_init(struct ntfs_sb_info *sbi) goto out; } - root =resident_data (attr); -if (root->type !=ATTR_ZERO || + root =resident_data_ex (attr,sizeof (struct INDEX_ROOT )); +if (!root || root->type !=ATTR_ZERO || root->rule !=NTFS_COLLATION_TYPE_UINTS ) { err = -EINVAL ; goto out;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 873/1424 arm64: dts: rockchip: Fix Gru WLAN sideband interrupt
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Fabio Estevam <[email protected]>
[ Upstream commit a761818d9ee11183df0aefd16bf9fe46cc1c4c6d ]
The Marvell WLAN host wake interrupt is wired to GPIO0 8 and is not one of the PCI INTx interrupts. The PCI device schema therefore interprets the two-cell GPIO interrupt specifier as an invalid PCI interrupt and reports dtbs_check warnings:
pcie@0,0: wifi@0,0:interrupts:0:0: 8 is not one of [1, 2, 3, 4] pcie@0,0: wifi@0,0:interrupts:0: [8, 8] is too long
Describe the sideband interrupt with interrupts-extended, which explicitly carries the interrupt controller and removes the ambiguity.
--- arch/arm64/boot/dts/rockchip/rk3399-gru-chromebook.dtsi | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
arch/arm64/boot/dts/rockchip/rk3399-gru-chromebook.dtsi +1 -2
@@ -510,8 +510,7 @@ &pci_rootport { mvl_wifi: wifi@0,0 { compatible = "pci1b4b,2b42"; reg = <0x0000 0x0 0x0 0x0 0x0>; - interrupt-parent = <&gpio0>; - interrupts = <8 IRQ_TYPE_LEVEL_LOW>; + interrupts-extended = <&gpio0 8 IRQ_TYPE_LEVEL_LOW>; pinctrl-names = "default"; pinctrl-0 = <&wlan_host_wake_l>; wakeup-source;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 874/1424 ARM: lpc32xx: only run SoC init on LPC32xx hardware
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Karl Mehltretter <[email protected]>
[ Upstream commit 717ea4000867e6dffee5e1ed92150a9704ae9f68 ]
lpc32xx_check_uid() and lpc32xx_pm_init() are arch_initcalls that poke LPC32xx-only registers. Since the multiplatform conversion they also run on other ARCH_MULTI_V5 boards where access faults e.g. on versatile:
Unable to handle kernel paging request at virtual address f4004130 PC is at lpc32xx_check_uid+0x2c/0x9c
Drop the arch_initcall() registrations and call both functions directly from lpc3250_machine_init(), the machine's .init_machine hook. The calls are placed in link order (common.c, pm.c, phy3250.c) to keep their previous relative ordering.
--- arch/arm/mach-lpc32xx/common.c | 5 +---- arch/arm/mach-lpc32xx/common.h | 2 ++ arch/arm/mach-lpc32xx/phy3250.c | 2 ++ arch/arm/mach-lpc32xx/pm.c | 5 +---- 4 files changed, 6 insertions(+), 8 deletions(-)
arch/arm/mach-lpc32xx/common.c +1 -4
@@ -106,7 +106,7 @@ void __init lpc32xx_map_io(void)iotable_init (lpc32xx_io_desc,ARRAY_SIZE (lpc32xx_io_desc)); } -static int __init lpc32xx_check_uid (void ) +void __init lpc32xx_check_uid (void ) {u32 uid[4 ];
@@ -119,7 +119,4 @@ static int __init lpc32xx_check_uid(void) system_serial_low = uid[0 ]; system_serial_high = uid[1 ]; } - -return 1 ; } -arch_initcall (lpc32xx_check_uid);
arch/arm/mach-lpc32xx/common.h +2 -0
@@ -16,6 +16,8 @@* Other arch specific structures and functions */ extern void __init lpc32xx_map_io (void ); +extern void __init lpc32xx_check_uid (void ); +extern void __init lpc32xx_pm_init (void );extern void __init lpc32xx_serial_init (void );/*
arch/arm/mach-lpc32xx/phy3250.c +2 -0
@@ -71,6 +71,8 @@ static const struct of_dev_auxdata lpc32xx_auxdata_lookup[] __initconst = {static void __init lpc3250_machine_init (void ) { +lpc32xx_check_uid (); +lpc32xx_pm_init ();lpc32xx_serial_init ();of_platform_default_populate (NULL , lpc32xx_auxdata_lookup,NULL );
arch/arm/mach-lpc32xx/pm.c +1 -4
@@ -120,7 +120,7 @@ static const struct platform_suspend_ops lpc32xx_pm_ops = {#define EMC_DYN_MEM_CTRL_OFS 0x20#define EMC_SRMMC (1 << 3)#define EMC_CTRL_REG io_p2v(LPC32XX_EMC_BASE + EMC_DYN_MEM_CTRL_OFS) -static int __init lpc32xx_pm_init (void ) +void __init lpc32xx_pm_init (void ) {/* * Setup SDRAM self-refresh clock to automatically disable o
@@ -129,7 +129,4 @@ static int __init lpc32xx_pm_init(void)__raw_writel (__raw_readl (EMC_CTRL_REG ) |EMC_SRMMC ,EMC_CTRL_REG );suspend_set_ops (&lpc32xx_pm_ops); - -return 0 ; } -arch_initcall (lpc32xx_pm_init);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 875/1424 selftests/bpf: Fix incorrect error checking for pthread_create
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Feng Yang <[email protected]>
[ Upstream commit b04b8d4e198aefc863e7b702ececb957845b0c25 ]
pthread_create returns 0 on success and a positive error code on failure; it never returns a negative value. The current conditional branch can never be taken. Failures during thread creation are silently ignored, which will lead to invalid memory access when waiting on threads or dereferencing thread handles later.
--- tools/testing/selftests/bpf/test_progs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/testing/selftests/bpf/test_progs.c +1 -1
@@ -1391,7 +1391,7 @@ static void server_main(void) data[i].worker_id = i; data[i].sock_fd = env.worker_socks[i]; rc =pthread_create (&dispatcher_threads[i],NULL , dispatch_thread, &data[i]); -if (rc <0 ) { +if (rc) {perror ("Failed to launch dispatcher thread" );exit (EXIT_ERR_SETUP_INFRA ); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 876/1424 selftests/bpf: Fix memory leak on subtest_states reallocation
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Feng Yang <[email protected]>
[ Upstream commit 06efb01c6530e9cfc247178cb96aa8adb3beaf61 ]
Fix memory leak in subtest_states reallocation,
and revert subtest_num if allocation fails.
--- tools/testing/selftests/bpf/test_progs.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
tools/testing/selftests/bpf/test_progs.c +5 -4
@@ -447,18 +447,19 @@ bool test__start_subtest(const char *subtest_name)struct test_state *state = env.test_state;struct subtest_state *subtest_state;size_t sub_state_size =sizeof (*subtest_state); +void *tmp;if (env.subtest_state)test__end_subtest (); state->subtest_num++; - state->subtest_states = -realloc (state->subtest_states, - state->subtest_num * sub_state_size); -if (!state->subtest_states) { + tmp =realloc (state->subtest_states, state->subtest_num * sub_state_size); +if (!tmp) { + state->subtest_num--;fprintf (stderr,"Not enough memory to allocate subtest result\n" );return false; } + state->subtest_states = tmp; subtest_state = &state->subtest_states[state->subtest_num -1 ];
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 877/1424 cxl/region: Fix use-after-free in find_pos_and_ways() error path
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alison Schofield <[email protected]>
[ Upstream commit 15da704b732332cc1e8f121f624e5e6c05124c5d ]
The error path releases its reference to a switch decoder before logging an error that includes the decoder name. If the released reference is the last one, the decoder can be freed before the error message accesses its name.
Drop the reference after the error is reported.
--- drivers/cxl/core/region.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-)
drivers/cxl/core/region.c +3 -4
@@ -1651,14 +1651,13 @@ static int find_pos_and_ways(struct cxl_port *port, struct range *range,break ; } } -put_device (dev); -if (rc)dev_err (port->uport_dev,"failed to find %s:%s in target list of %s\n" ,dev_name (&port->dev), -dev_name (port->parent_dport->dport_dev), -dev_name (&cxlsd->cxld.dev)); +dev_name (port->parent_dport->dport_dev),dev_name (dev)); + +put_device (dev);return rc; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 878/1424 pinctrl: mediatek: Use C99 initializers in PINCTRL_PIN_GROUP()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andy Shevchenko <[email protected]>
[ Upstream commit bb5eace1562fcef3c7ac9d0bd3e01af1187e46d0 ]
For the better flexibility use C99 initializers in PINCTRL_PIN_GROUP().
Stable-dep-of: 88292b7103d2 ("pinctrl: mediatek: free EINT resources on unbind")
--- drivers/pinctrl/mediatek/pinctrl-moore.h | 12 ++++++------ drivers/pinctrl/mediatek/pinctrl-paris.h | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-)
drivers/pinctrl/mediatek/pinctrl-moore.h +6 -6
@@ -37,12 +37,12 @@ .funcs = NULL, \ } -#define PINCTRL_PIN_GROUP (name, id) \ - { \ - name, \ - id##_pins, \ - ARRAY_SIZE(id##_pins), \ - id##_funcs, \ +#define PINCTRL_PIN_GROUP (_name_, id) \ + { \ + .name = _name_, \ + .pins = id##_pins, \ + .num_pins = ARRAY_SIZE(id##_pins), \ + .data = id##_funcs, \ } int mtk_moore_pinctrl_probe(struct platform_device *pdev,
drivers/pinctrl/mediatek/pinctrl-paris.h +6 -6
@@ -49,12 +49,12 @@ __VA_ARGS__, { } }, \ } -#define PINCTRL_PIN_GROUP (name, id) \ - { \ - name, \ - id##_pins, \ - ARRAY_SIZE(id##_pins), \ - id##_funcs, \ +#define PINCTRL_PIN_GROUP (_name_, id) \ + { \ + .name = _name_, \ + .pins = id##_pins, \ + .num_pins = ARRAY_SIZE(id##_pins), \ + .data = id##_funcs, \ }int mtk_paris_pinctrl_probe (struct platform_device *pdev);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 879/1424 pinctrl: mediatek: Add EINT support for multiple addresses
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hao Chang <[email protected]>
[ Upstream commit 3ef9f710efcb5cc1335b5b09c16c757f703d7e5f ]
For flexible routing, eint will be divided into 5 bases, and it will obtain the operation address through the pins array.
Stable-dep-of: 88292b7103d2 ("pinctrl: mediatek: free EINT resources on unbind")
--- drivers/pinctrl/mediatek/mtk-eint.c | 313 +++++++++++------- drivers/pinctrl/mediatek/mtk-eint.h | 23 +- .../pinctrl/mediatek/pinctrl-mtk-common-v2.c | 37 ++- .../pinctrl/mediatek/pinctrl-mtk-common-v2.h | 1 + drivers/pinctrl/mediatek/pinctrl-paris.h | 7 + 5 files changed, 254 insertions(+), 127 deletions(-)
drivers/pinctrl/mediatek/mtk-eint.c +197 -116
@@ -1,11 +1,13 @@// SPDX-License-Identifier: GPL-2.0 -// Copyright (c) 2014-2018 MediaTek Inc. +// Copyright (c) 2014-2025 MediaTek Inc. /* * Library for MediaTek External Interrupt Support * * Author: Maoguang Meng <[email protected]> * Sean Wang <[email protected]> +* Hao Chang <[email protected]> +* Qingliang Li <[email protected]> * */
@@ -20,6 +22,7 @@#include <linux/platform_device.h> #include "mtk-eint.h" +#include "pinctrl-mtk-common-v2.h" #define MTK_EINT_EDGE_SENSITIVE 0#define MTK_EINT_LEVEL_SENSITIVE 1
@@ -68,13 +71,11 @@ static void __iomem *mtk_eint_get_offset(struct mtk_eint *eint, unsigned int eint_num, unsigned int offset) { -unsigned int eint_base =0 ; +unsigned int idx = eint->pins[eint_num].index; +unsigned int inst = eint->pins[eint_num].instance;void __iomem *reg; -if (eint_num >= eint->hw->ap_num) - eint_base = eint->hw->ap_num; - - reg = eint->base + offset + ((eint_num - eint_base) /32 ) *4 ; + reg = eint->base[inst] + offset + (idx /32 *4 );return reg; }
@@ -83,7 +84,7 @@ static unsigned int mtk_eint_can_en_debounce(struct mtk_eint *eint, unsigned int eint_num) {unsigned int sens; -unsigned int bit =BIT (eint_num %32 ); +unsigned int bit =BIT (eint->pins[eint_num].index %32 );void __iomem *reg =mtk_eint_get_offset (eint, eint_num, eint->regs->sens);
@@ -92,7 +93,7 @@ static unsigned int mtk_eint_can_en_debounce(struct mtk_eint *eint,else sens =MTK_EINT_EDGE_SENSITIVE ; -if (eint_num < eint->hw->db_cnt && sens !=MTK_EINT_EDGE_SENSITIVE ) +if (eint->pins[eint_num].debounce && sens !=MTK_EINT_EDGE_SENSITIVE )return 1 ;else return 0 ;
@@ -102,9 +103,9 @@ static int mtk_eint_flip_edge(struct mtk_eint *eint, int hwirq) {int start_level, curr_level;unsigned int reg_offset; -u32 mask =BIT (hwirq &0x1f ); -u32 port = (hwirq >>5 ) & eint->hw->port_mask; -void __iomem *reg = eint->base + (port <<2 ); +unsigned int mask =BIT (eint->pins[hwirq].index &0x1f ); +unsigned int port = (eint->pins[hwirq].index >>5 ) & eint->hw->port_mask; +void __iomem *reg = eint->base[eint->pins[hwirq].instance] + (port <<2 ); curr_level = eint->gpio_xlate->get_gpio_state (eint->pctl, hwirq);
@@ -126,11 +127,13 @@ static int mtk_eint_flip_edge(struct mtk_eint *eint, int hwirq)static void mtk_eint_mask (struct irq_data *d) {struct mtk_eint *eint =irq_data_get_irq_chip_data (d); -u32 mask =BIT (d->hwirq &0x1f ); +unsigned int idx = eint->pins[d->hwirq].index; +unsigned int inst = eint->pins[d->hwirq].instance; +unsigned int mask =BIT (idx &0x1f );void __iomem *reg =mtk_eint_get_offset (eint, d->hwirq, eint->regs->mask_set); - eint->cur_mask[d->hwirq >>5 ] &= ~mask; + eint->cur_mask[inst][idx >>5 ] &= ~mask;writel (mask, reg); }
@@ -138,22 +141,24 @@ static void mtk_eint_mask(struct irq_data *d)static void mtk_eint_unmask (struct irq_data *d) {struct mtk_eint *eint =irq_data_get_irq_chip_data (d); -u32 mask =BIT (d->hwirq &0x1f ); +unsigned int idx = eint->pins[d->hwirq].index; +unsigned int inst = eint->pins[d->hwirq].instance; +unsigned int mask =BIT (idx &0x1f );void __iomem *reg =mtk_eint_get_offset (eint, d->hwirq, eint->regs->mask_clr); - eint->cur_mask[d->hwirq >>5 ] |= mask; + eint->cur_mask[inst][idx >>5 ] |= mask;writel (mask, reg); -if (eint->dual_edge[d->hwirq]) +if (eint->pins[d->hwirq].dual_edge)mtk_eint_flip_edge (eint, d->hwirq); }static unsigned int mtk_eint_get_mask (struct mtk_eint *eint,unsigned int eint_num) { -unsigned int bit =BIT (eint_num %32 ); +unsigned int bit =BIT (eint->pins[eint_num].index %32 );void __iomem *reg =mtk_eint_get_offset (eint, eint_num, eint->regs->mask);
@@ -163,7 +168,7 @@ static unsigned int mtk_eint_get_mask(struct mtk_eint *eint,static void mtk_eint_ack (struct irq_data *d) {struct mtk_eint *eint =irq_data_get_irq_chip_data (d); -u32 mask =BIT (d->hwirq &0x1f ); +unsigned int mask =BIT (eint->pins[d->hwirq].index &0x1f );void __iomem *reg =mtk_eint_get_offset (eint, d->hwirq, eint->regs->ack);
@@ -174,7 +179,7 @@ static int mtk_eint_set_type(struct irq_data *d, unsigned int type) {struct mtk_eint *eint =irq_data_get_irq_chip_data (d);bool masked; -u32 mask =BIT (d->hwirq &0x1f ); +unsigned int mask =BIT (eint->pins[d->hwirq].index &0x1f );void __iomem *reg; if (((type & IRQ_TYPE_EDGE_BOTH) && (type & IRQ_TYPE_LEVEL_MASK)) ||
@@ -186,9 +191,9 @@ static int mtk_eint_set_type(struct irq_data *d, unsigned int type) }if ((type &IRQ_TYPE_EDGE_BOTH ) ==IRQ_TYPE_EDGE_BOTH ) - eint->dual_edge[d->hwirq] =1 ; + eint->pins[d->hwirq].dual_edge =1 ;else - eint->dual_edge[d->hwirq] =0 ; + eint->pins[d->hwirq].dual_edge =0 ;if (!mtk_eint_get_mask (eint, d->hwirq)) {mtk_eint_mask (d);
@@ -223,27 +228,32 @@ static int mtk_eint_set_type(struct irq_data *d, unsigned int type)static int mtk_eint_irq_set_wake (struct irq_data *d,unsigned int on) {struct mtk_eint *eint =irq_data_get_irq_chip_data (d); -int shift = d->hwirq &0x1f ; -int reg = d->hwirq >>5 ; +unsigned int idx = eint->pins[d->hwirq].index; +unsigned int inst = eint->pins[d->hwirq].instance; +unsigned int shift = idx &0x1f ; +unsigned int port = idx >>5 ;if (on) - eint->wake_mask[reg] |=BIT (shift); + eint->wake_mask[inst][port] |=BIT (shift);else - eint->wake_mask[reg] &= ~BIT (shift); + eint->wake_mask[inst][port] &= ~BIT (shift);return 0 ; }static void mtk_eint_chip_write_mask (const struct mtk_eint *eint, -void __iomem *base,u32 *buf) +void __iomem *base,unsigned int **buf) { -int port; +int inst, port, port_num;void __iomem *reg; -for (port =0 ; port < eint->hw->ports; port++) { - reg = base + (port <<2 ); -writel_relaxed (~buf[port], reg + eint->regs->mask_set); -writel_relaxed (buf[port], reg + eint->regs->mask_clr); +for (inst =0 ; inst < eint->nbase; inst++) { + port_num =DIV_ROUND_UP (eint->base_pin_num[inst],32 ); +for (port =0 ; port < port_num; port++) { + reg = eint->base[inst] + (port <<2 ); +writel_relaxed (~buf[inst][port], reg + eint->regs->mask_set); +writel_relaxed (buf[inst][port], reg + eint->regs->mask_clr); + } } }
@@ -303,15 +313,18 @@ static struct irq_chip mtk_eint_irq_chip = {static unsigned int mtk_eint_hw_init (struct mtk_eint *eint) { -void __iomem *dom_en = eint->base + eint->regs->dom_en; -void __iomem *mask_set = eint->base + eint->regs->mask_set; -unsigned int i; - -for (i =0 ; i < eint->hw->ap_num; i +=32 ) { -writel (0xffffffff , dom_en); -writel (0xffffffff , mask_set); - dom_en +=4 ; - mask_set +=4 ; +void __iomem *dom_reg, *mask_reg; +unsigned int i, j; + +for (i =0 ; i < eint->nbase; i++) { + dom_reg = eint->base[i] + eint->regs->dom_en; + mask_reg = eint->base[i] + eint->regs->mask_set; +for (j =0 ; j < eint->base_pin_num[i]; j +=32 ) { +writel (0xffffffff , dom_reg); +writel (0xffffffff , mask_reg); + dom_reg +=4 ; + mask_reg +=4 ; + } }return 0 ;
@@ -322,14 +335,16 @@ mtk_eint_debounce_process(struct mtk_eint *eint, int index) {unsigned int rst, ctrl_offset;unsigned int bit, dbnc; +unsigned int inst = eint->pins[index].instance; +unsigned int idx = eint->pins[index].index; - ctrl_offset = (index /4 ) *4 + eint->regs->dbnc_ctrl; - dbnc =readl (eint->base + ctrl_offset); - bit =MTK_EINT_DBNC_SET_EN << ((index %4 ) *8 ); + ctrl_offset = (idx /4 ) *4 + eint->regs->dbnc_ctrl; + dbnc =readl (eint->base[inst] + ctrl_offset); + bit =MTK_EINT_DBNC_SET_EN << ((idx %4 ) *8 );if ((bit & dbnc) >0 ) { - ctrl_offset = (index /4 ) *4 + eint->regs->dbnc_set; - rst =MTK_EINT_DBNC_RST_BIT << ((index %4 ) *8 ); -writel (rst, eint->base + ctrl_offset); + ctrl_offset = (idx /4 ) *4 + eint->regs->dbnc_set; + rst =MTK_EINT_DBNC_RST_BIT << ((idx %4 ) *8 ); +writel (rst, eint->base[inst] + ctrl_offset); } }
@@ -337,65 +352,68 @@ static void mtk_eint_irq_handler(struct irq_desc *desc) {struct irq_chip *chip =irq_desc_get_chip (desc);struct mtk_eint *eint =irq_desc_get_handler_data (desc); -unsigned int status, eint_num; -int offset, mask_offset, index; -void __iomem *reg =mtk_eint_get_offset (eint,0 , eint->regs->stat); +unsigned int i, j, port, status, shift, mask, eint_num; +void __iomem *reg;int dual_edge, start_level, curr_level;chained_irq_enter (chip, desc); -for (eint_num =0 ; eint_num < eint->hw->ap_num; eint_num +=32 , - reg +=4 ) { - status =readl (reg); -while (status) { - offset =__ffs (status); - mask_offset = eint_num >>5 ; - index = eint_num + offset; - status &= ~BIT (offset); - -/* -* If we get an interrupt on pin that was only required -* for wake (but no real interrupt requested), mask the -* interrupt (as would mtk_eint_resume do anyway later -* in the resume sequence). -*/ -if (eint->wake_mask[mask_offset] &BIT (offset) && - !(eint->cur_mask[mask_offset] &BIT (offset))) { -writel_relaxed (BIT (offset), reg - - eint->regs->stat + - eint->regs->mask_set); - } - - dual_edge = eint->dual_edge[index]; -if (dual_edge) { -/* -* Clear soft-irq in case we raised it last -* time. -*/ -writel (BIT (offset), reg - eint->regs->stat + - eint->regs->soft_clr); - - start_level = - eint->gpio_xlate->get_gpio_state (eint->pctl, - index); - } - -generic_handle_domain_irq (eint->domain, index); - -if (dual_edge) { - curr_level =mtk_eint_flip_edge (eint, index); +for (i =0 ; i < eint->nbase; i++) { +for (j =0 ; j < eint->base_pin_num[i]; j +=32 ) { + port = j >>5 ; + status =readl (eint->base[i] + port *4 + eint->regs->stat); +while (status) { + shift =__ffs (status); + status &= ~BIT (shift); + mask =BIT (shift); + eint_num = eint->pin_list[i][shift + j];/* -* If level changed, we might lost one edge -* interrupt, raised it through soft-irq. +* If we get an interrupt on pin that was only required +* for wake (but no real interrupt requested), mask the +* interrupt (as would mtk_eint_resume do anyway later +* in the resume sequence). */ -if (start_level != curr_level) -writel (BIT (offset), reg - - eint->regs->stat + - eint->regs->soft_set); +if (eint->wake_mask[i][port] & mask && + !(eint->cur_mask[i][port] & mask)) { + reg =mtk_eint_get_offset (eint, eint_num, + eint->regs->mask_set); +writel_relaxed (mask, reg); + } + + dual_edge = eint->pins[eint_num].dual_edge; +if (dual_edge) { +/* +* Clear soft-irq in case we raised it last +* time. +*/ + reg =mtk_eint_get_offset (eint, eint_num, + eint->regs->soft_clr); +writel (mask, reg); + + start_level = + eint->gpio_xlate->get_gpio_state (eint->pctl, + eint_num); + } + +generic_handle_domain_irq (eint->domain, eint_num); + +if (dual_edge) { + curr_level =mtk_eint_flip_edge (eint, eint_num); + +/* +* If level changed, we might lost one edge +* interrupt, raised it through soft-irq. +*/ +if (start_level != curr_level) { + reg =mtk_eint_get_offset (eint, eint_num, + eint->regs->soft_set); +writel (mask, reg); + } + } + +if (eint->pins[eint_num].debounce) +mtk_eint_debounce_process (eint, eint_num); } - -if (index < eint->hw->db_cnt) -mtk_eint_debounce_process (eint, index); } }chained_irq_exit (chip, desc);
@@ -423,6 +441,8 @@ int mtk_eint_set_debounce(struct mtk_eint *eint, unsigned long eint_num,int virq, eint_offset;unsigned int set_offset, bit, clr_bit, clr_offset, rst, i, unmask, dbnc; +unsigned int inst = eint->pins[eint_num].instance; +unsigned int idx = eint->pins[eint_num].index;struct irq_data *d;if (!eint->hw->db_time)
@@ -432,8 +452,8 @@ int mtk_eint_set_debounce(struct mtk_eint *eint, unsigned long eint_num, eint_offset = (eint_num %4 ) *8 ; d =irq_get_irq_data (virq); - set_offset = (eint_num /4 ) *4 + eint->regs->dbnc_set; - clr_offset = (eint_num /4 ) *4 + eint->regs->dbnc_clr; + set_offset = (idx /4 ) *4 + eint->regs->dbnc_set; + clr_offset = (idx /4 ) *4 + eint->regs->dbnc_clr;if (!mtk_eint_can_en_debounce (eint, eint_num))return -EINVAL ;
@@ -454,12 +474,12 @@ int mtk_eint_set_debounce(struct mtk_eint *eint, unsigned long eint_num, } clr_bit =0xff << eint_offset; -writel (clr_bit, eint->base + clr_offset); +writel (clr_bit, eint->base[inst] + clr_offset); bit = ((dbnc <<MTK_EINT_DBNC_SET_DBNC_BITS ) |MTK_EINT_DBNC_SET_EN ) << eint_offset; rst =MTK_EINT_DBNC_RST_BIT << eint_offset; -writel (rst | bit, eint->base + set_offset); +writel (rst | bit, eint->base[inst] + set_offset);/* * Delay a while (more than 2T) to wait for hw debounce counter reset
@@ -487,32 +507,69 @@ EXPORT_SYMBOL_GPL(mtk_eint_find_irq);int mtk_eint_do_init (struct mtk_eint *eint) { -int i; +unsigned int size, i, port, inst =0 ; +struct mtk_pinctrl *hw = (struct mtk_pinctrl *)eint->pctl;/* If clients don't assign a specific regs, let's use generic one */ if (!eint->regs) eint->regs = &mtk_generic_eint_regs; - eint->wake_mask =devm_kcalloc (eint->dev, eint->hw->ports, -sizeof (*eint->wake_mask),GFP_KERNEL ); -if (!eint->wake_mask) + eint->base_pin_num =devm_kmalloc_array (eint->dev, eint->nbase,sizeof (u16), +GFP_KERNEL | __GFP_ZERO); +if (!eint->base_pin_num)return -ENOMEM ; - eint->cur_mask =devm_kcalloc (eint->dev, eint->hw->ports, -sizeof (*eint->cur_mask),GFP_KERNEL ); -if (!eint->cur_mask) -return -ENOMEM ; +if (eint->nbase ==1 ) { + size = eint->hw->ap_num *sizeof (struct mtk_eint_pin ); + eint->pins =devm_kmalloc (eint->dev, size,GFP_KERNEL ); +if (!eint->pins) + goto err_pins; + + eint->base_pin_num[inst] = eint->hw->ap_num; +for (i =0 ; i < eint->hw->ap_num; i++) { + eint->pins[i].instance = inst; + eint->pins[i].index = i; + eint->pins[i].debounce = (i < eint->hw->db_cnt) ?1 :0 ; + } + } - eint->dual_edge =devm_kcalloc (eint->dev, eint->hw->ap_num, -sizeof (int ),GFP_KERNEL ); -if (!eint->dual_edge) -return -ENOMEM ; +if (hw && hw->soc && hw->soc->eint_pin) { + eint->pins = hw->soc->eint_pin; +for (i =0 ; i < eint->hw->ap_num; i++) { + inst = eint->pins[i].instance; +if (inst >= eint->nbase) +continue ; + eint->base_pin_num[inst]++; + } + } + + eint->pin_list =devm_kmalloc (eint->dev, eint->nbase *sizeof (u16 *),GFP_KERNEL ); +if (!eint->pin_list) + goto err_pin_list; + + eint->wake_mask =devm_kmalloc (eint->dev, eint->nbase *sizeof (u32 *),GFP_KERNEL ); +if (!eint->wake_mask) + goto err_wake_mask; + + eint->cur_mask =devm_kmalloc (eint->dev, eint->nbase *sizeof (u32 *),GFP_KERNEL ); +if (!eint->cur_mask) + goto err_cur_mask; + +for (i =0 ; i < eint->nbase; i++) { + eint->pin_list[i] =devm_kzalloc (eint->dev, eint->base_pin_num[i] *sizeof (u16), +GFP_KERNEL ); + port =DIV_ROUND_UP (eint->base_pin_num[i],32 ); + eint->wake_mask[i] =devm_kzalloc (eint->dev, port *sizeof (u32),GFP_KERNEL ); + eint->cur_mask[i] =devm_kzalloc (eint->dev, port *sizeof (u32),GFP_KERNEL ); +if (!eint->pin_list[i] || !eint->wake_mask[i] || !eint->cur_mask[i]) + goto err_eint; + } eint->domain =irq_domain_add_linear (eint->dev->of_node, eint->hw->ap_num, &irq_domain_simple_ops,NULL );if (!eint->domain) -return -ENOMEM ; + goto err_eint;if (eint->hw->db_time) {for (i =0 ; i <MTK_EINT_DBNC_MAX ; i++)
@@ -523,8 +580,11 @@ int mtk_eint_do_init(struct mtk_eint *eint)mtk_eint_hw_init (eint);for (i =0 ; i < eint->hw->ap_num; i++) { + inst = eint->pins[i].instance; +if (inst >= eint->nbase) +continue ; + eint->pin_list[inst][eint->pins[i].index] = i;int virq =irq_create_mapping (eint->domain, i); -irq_set_chip_and_handler (virq, &mtk_eint_irq_chip, handle_level_irq);irq_set_chip_data (virq, eint);
@@ -534,6 +594,27 @@ int mtk_eint_do_init(struct mtk_eint *eint) eint);return 0 ; + +err_eint: +for (i =0 ; i < eint->nbase; i++) { +if (eint->cur_mask[i]) +devm_kfree (eint->dev, eint->cur_mask[i]); +if (eint->wake_mask[i]) +devm_kfree (eint->dev, eint->wake_mask[i]); +if (eint->pin_list[i]) +devm_kfree (eint->dev, eint->pin_list[i]); + } +devm_kfree (eint->dev, eint->cur_mask); +err_cur_mask: +devm_kfree (eint->dev, eint->wake_mask); +err_wake_mask: +devm_kfree (eint->dev, eint->pin_list); +err_pin_list: +if (eint->nbase ==1 ) +devm_kfree (eint->dev, eint->pins); +err_pins: +devm_kfree (eint->dev, eint->base_pin_num); +return -ENOMEM ; }EXPORT_SYMBOL_GPL (mtk_eint_do_init);
drivers/pinctrl/mediatek/mtk-eint.h +18 -5
@@ -1,10 +1,11 @@/* SPDX-License-Identifier: GPL-2.0 */ /* -* Copyright (C) 2014-2018 MediaTek Inc. +* Copyright (C) 2014-2025 MediaTek Inc. * * Author: Maoguang Meng <[email protected]> * Sean Wang <[email protected]> -* +* Hao Chang <[email protected]> +* Qingliang Li <[email protected]> */ #ifndef __MTK_EINT_H#define __MTK_EINT_H
@@ -40,6 +41,14 @@ struct mtk_eint_hw {const unsigned int *db_time; }; +struct mtk_eint_pin { +u16 number; +u8 instance; +u8 index; +bool debounce; +bool dual_edge; +}; +extern const unsigned int debounce_time_mt2701[];extern const unsigned int debounce_time_mt6765[];extern const unsigned int debounce_time_mt6795[];
@@ -56,17 +65,21 @@ struct mtk_eint_xt {struct mtk_eint {struct device *dev; -void __iomem *base; +void __iomem **base; +u8 nbase; +u16 *base_pin_num;struct irq_domain *domain;int irq;int *dual_edge; -u32 *wake_mask; -u32 *cur_mask; +u16 **pin_list; +u32 **wake_mask; +u32 **cur_mask;/* Used to fit into various EINT device */ const struct mtk_eint_hw *hw;const struct mtk_eint_regs *regs; +struct mtk_eint_pin *pins;u16 num_db_time;/* Used to fit into various pinctrl device */
drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c +31 -6
@@ -13,6 +13,7 @@#include <linux/platform_device.h> #include <linux/io.h> #include <linux/module.h> +#include <linux/of_address.h> #include <linux/of_irq.h> #include "mtk-eint.h"
@@ -367,7 +368,7 @@ static const struct mtk_eint_xt mtk_eint_xt = {int mtk_build_eint (struct mtk_pinctrl *hw,struct platform_device *pdev) {struct device_node *np = pdev->dev.of_node; -int ret; +int ret, i, j, count_reg_names;if (!IS_ENABLED (CONFIG_EINT_MTK ))return 0 ;
@@ -379,10 +380,24 @@ int mtk_build_eint(struct mtk_pinctrl *hw, struct platform_device *pdev)if (!hw->eint)return -ENOMEM ; - hw->eint->base =devm_platform_ioremap_resource_byname (pdev,"eint" ); -if (IS_ERR (hw->eint->base)) { - ret =PTR_ERR (hw->eint->base); - goto err_free_eint; + count_reg_names =of_property_count_strings (np,"reg-names" ); +if (count_reg_names < hw->soc->nbase_names) +return -EINVAL ; + + hw->eint->nbase = count_reg_names - hw->soc->nbase_names; + hw->eint->base =devm_kmalloc_array (&pdev->dev, hw->eint->nbase, +sizeof (*hw->eint->base),GFP_KERNEL | __GFP_ZERO); +if (!hw->eint->base) { + ret = -ENOMEM ; + goto err_free_base; + } + +for (i = hw->soc->nbase_names, j =0 ; i < count_reg_names; i++, j++) { + hw->eint->base[j] =of_iomap (np, i); +if (IS_ERR (hw->eint->base[j])) { + ret =PTR_ERR (hw->eint->base[j]); + goto err_free_eint; + } } hw->eint->irq =irq_of_parse_and_map (np,0 );
@@ -401,9 +416,19 @@ int mtk_build_eint(struct mtk_pinctrl *hw, struct platform_device *pdev) hw->eint->pctl = hw; hw->eint->gpio_xlate = &mtk_eint_xt; -return mtk_eint_do_init (hw->eint); + ret =mtk_eint_do_init (hw->eint); +if (ret) + goto err_free_eint; + +return 0 ; err_free_eint: +for (j =0 ; j < hw->eint->nbase; j++) { +if (hw->eint->base[j]) +iounmap (hw->eint->base[j]); + } +devm_kfree (hw->dev, hw->eint->base); +err_free_base:devm_kfree (hw->dev, hw->eint); hw->eint =NULL ;return ret;
drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h +1 -0
@@ -241,6 +241,7 @@ struct mtk_pin_soc {unsigned int nfuncs;const struct mtk_eint_regs *eint_regs;const struct mtk_eint_hw *eint_hw; +struct mtk_eint_pin *eint_pin;/* Specific parameters per SoC */ u8 gpio_m;
drivers/pinctrl/mediatek/pinctrl-paris.h +7 -0
@@ -49,6 +49,13 @@ __VA_ARGS__, { } }, \ } +#define MTK_EINT_PIN (_number, _instance, _index, _debounce) { \ + .number = _number, \ + .instance = _instance, \ + .index = _index, \ + .debounce = _debounce, \ + } +#define PINCTRL_PIN_GROUP (_name_, id) \ { \ .name = _name_, \
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 880/1424 pinctrl: mediatek: Fix the invalid conditions
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hao Chang <[email protected]>
[ Upstream commit 86dee87f4b2e6ac119b03810e58723d0b27787a4 ]
The variable count_reg_names is defined as an int type and cannot be directly compared to an unsigned int. To resolve this issue, first verify the correctness of count_reg_names.
Stable-dep-of: 88292b7103d2 ("pinctrl: mediatek: free EINT resources on unbind")
--- drivers/pinctrl/mediatek/mtk-eint.c | 4 ++-- drivers/pinctrl/mediatek/mtk-eint.h | 2 +- drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c | 7 +++++-- 3 files changed, 8 insertions(+), 5 deletions(-)
drivers/pinctrl/mediatek/mtk-eint.c +2 -2
@@ -507,7 +507,7 @@ EXPORT_SYMBOL_GPL(mtk_eint_find_irq);int mtk_eint_do_init (struct mtk_eint *eint) { -unsigned int size, i, port, inst =0 ; +unsigned int size, i, port, virq, inst =0 ;struct mtk_pinctrl *hw = (struct mtk_pinctrl *)eint->pctl;/* If clients don't assign a specific regs, let's use generic one */
@@ -584,7 +584,7 @@ int mtk_eint_do_init(struct mtk_eint *eint)if (inst >= eint->nbase)continue ; eint->pin_list[inst][eint->pins[i].index] = i; -int virq =irq_create_mapping (eint->domain, i); + virq =irq_create_mapping (eint->domain, i);irq_set_chip_and_handler (virq, &mtk_eint_irq_chip, handle_level_irq);irq_set_chip_data (virq, eint);
drivers/pinctrl/mediatek/mtk-eint.h +1 -1
@@ -66,7 +66,7 @@ struct mtk_eint_xt {struct mtk_eint {struct device *dev;void __iomem **base; -u8 nbase; +int nbase;u16 *base_pin_num;struct irq_domain *domain;int irq;
drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c +5 -2
@@ -381,10 +381,13 @@ int mtk_build_eint(struct mtk_pinctrl *hw, struct platform_device *pdev)return -ENOMEM ; count_reg_names =of_property_count_strings (np,"reg-names" ); -if (count_reg_names < hw->soc->nbase_names) +if (count_reg_names <0 ) +return -EINVAL ; + + hw->eint->nbase = count_reg_names - (int )hw->soc->nbase_names; +if (hw->eint->nbase <=0 )return -EINVAL ; - hw->eint->nbase = count_reg_names - hw->soc->nbase_names; hw->eint->base =devm_kmalloc_array (&pdev->dev, hw->eint->nbase,sizeof (*hw->eint->base),GFP_KERNEL | __GFP_ZERO);if (!hw->eint->base) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 881/1424 pinctrl: mediatek: eint: Fix invalid pointer dereference for v1 platforms
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nícolas F. R. A. Prado <[email protected]>
[ Upstream commit 1c9977b263475373b31bbf86af94a5c9ae2be42c ]
Commit 3ef9f710efcb ("pinctrl: mediatek: Add EINT support for multiple addresses") introduced an access to the 'soc' field of struct mtk_pinctrl in mtk_eint_do_init() and for that an include of pinctrl-mtk-common-v2.h.
However, pinctrl drivers relying on the v1 common driver include pinctrl-mtk-common.h instead, which provides another definition of struct mtk_pinctrl that does not contain an 'soc' field.
Since mtk_eint_do_init() can be called both by v1 and v2 drivers, it will now try to dereference an invalid pointer when called on v1 platforms. This has been observed on Genio 350 EVK (MT8365), which crashes very early in boot (the kernel trace can only be seen with earlycon).
In order to fix this, since 'struct mtk_pinctrl' was only needed to get a 'struct mtk_eint_pin', make 'struct mtk_eint_pin' a parameter of mtk_eint_do_init() so that callers need to supply it, removing mtk_eint_do_init()'s dependency on any particular 'struct mtk_pinctrl'.
Stable-dep-of: 88292b7103d2 ("pinctrl: mediatek: free EINT resources on unbind")
--- drivers/pinctrl/mediatek/mtk-eint.c | 26 ++++++++----------- drivers/pinctrl/mediatek/mtk-eint.h | 5 ++-- .../pinctrl/mediatek/pinctrl-mtk-common-v2.c | 2 +- drivers/pinctrl/mediatek/pinctrl-mtk-common.c | 2 +- 4 files changed, 16 insertions(+), 19 deletions(-)
drivers/pinctrl/mediatek/mtk-eint.c +11 -15
@@ -22,7 +22,6 @@#include <linux/platform_device.h> #include "mtk-eint.h" -#include "pinctrl-mtk-common-v2.h" #define MTK_EINT_EDGE_SENSITIVE 0#define MTK_EINT_LEVEL_SENSITIVE 1
@@ -505,10 +504,9 @@ int mtk_eint_find_irq(struct mtk_eint *eint, unsigned long eint_n) }EXPORT_SYMBOL_GPL (mtk_eint_find_irq); -int mtk_eint_do_init (struct mtk_eint *eint) +int mtk_eint_do_init (struct mtk_eint *eint,struct mtk_eint_pin *eint_pin) {unsigned int size, i, port, virq, inst =0 ; -struct mtk_pinctrl *hw = (struct mtk_pinctrl *)eint->pctl;/* If clients don't assign a specific regs, let's use generic one */ if (!eint->regs)
@@ -519,7 +517,15 @@ int mtk_eint_do_init(struct mtk_eint *eint)if (!eint->base_pin_num)return -ENOMEM ; -if (eint->nbase ==1 ) { +if (eint_pin) { + eint->pins = eint_pin; +for (i =0 ; i < eint->hw->ap_num; i++) { + inst = eint->pins[i].instance; +if (inst >= eint->nbase) +continue ; + eint->base_pin_num[inst]++; + } + }else { size = eint->hw->ap_num *sizeof (struct mtk_eint_pin ); eint->pins =devm_kmalloc (eint->dev, size,GFP_KERNEL );if (!eint->pins)
@@ -533,16 +539,6 @@ int mtk_eint_do_init(struct mtk_eint *eint) } } -if (hw && hw->soc && hw->soc->eint_pin) { - eint->pins = hw->soc->eint_pin; -for (i =0 ; i < eint->hw->ap_num; i++) { - inst = eint->pins[i].instance; -if (inst >= eint->nbase) -continue ; - eint->base_pin_num[inst]++; - } - } - eint->pin_list =devm_kmalloc (eint->dev, eint->nbase *sizeof (u16 *),GFP_KERNEL );if (!eint->pin_list) goto err_pin_list;
@@ -610,7 +606,7 @@ int mtk_eint_do_init(struct mtk_eint *eint) err_wake_mask:devm_kfree (eint->dev, eint->pin_list); err_pin_list: -if (eint->nbase ==1 ) +if (!eint_pin)devm_kfree (eint->dev, eint->pins); err_pins:devm_kfree (eint->dev, eint->base_pin_num);
drivers/pinctrl/mediatek/mtk-eint.h +3 -2
@@ -88,7 +88,7 @@ struct mtk_eint { };#if IS_ENABLED (CONFIG_EINT_MTK ) -int mtk_eint_do_init (struct mtk_eint *eint); +int mtk_eint_do_init (struct mtk_eint *eint,struct mtk_eint_pin *eint_pin);int mtk_eint_do_suspend (struct mtk_eint *eint);int mtk_eint_do_resume (struct mtk_eint *eint); int mtk_eint_set_debounce(struct mtk_eint *eint, unsigned long eint_n,
@@ -96,7 +96,8 @@ int mtk_eint_set_debounce(struct mtk_eint *eint, unsigned long eint_n,int mtk_eint_find_irq (struct mtk_eint *eint,unsigned long eint_n);#else -static inline int mtk_eint_do_init (struct mtk_eint *eint) +static inline int mtk_eint_do_init (struct mtk_eint *eint, +struct mtk_eint_pin *eint_pin) {return -EOPNOTSUPP ; }
drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c +1 -1
@@ -419,7 +419,7 @@ int mtk_build_eint(struct mtk_pinctrl *hw, struct platform_device *pdev) hw->eint->pctl = hw; hw->eint->gpio_xlate = &mtk_eint_xt; - ret =mtk_eint_do_init (hw->eint); + ret =mtk_eint_do_init (hw->eint, hw->soc->eint_pin);if (ret) goto err_free_eint;
drivers/pinctrl/mediatek/pinctrl-mtk-common.c +1 -1
@@ -1042,7 +1042,7 @@ static int mtk_eint_init(struct mtk_pinctrl *pctl, struct platform_device *pdev) pctl->eint->pctl = pctl; pctl->eint->gpio_xlate = &mtk_eint_xt; -return mtk_eint_do_init (pctl->eint); +return mtk_eint_do_init (pctl->eint,NULL ); }/* This is used as a common probe function */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 882/1424 pinctrl: mediatek: free EINT resources on unbind
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Justin Yeh <[email protected]>
[ Upstream commit 88292b7103d260e3e606eb3bb2794060a5fde48e ]
mtk_eint_do_init() creates an IRQ domain, populates it with a mapping for every EINT line and installs a chained handler on the parent interrupt, but none of these are ever released. This was harmless while the drivers were built-in, but now that they can be built as modules and unbound/rmmod'd it leaves behind a dangling IRQ domain, interrupt mappings whose chip data points at freed memory, and a chained handler that keeps firing into that freed data.
The plain allocations in mtk_eint_do_init() already use the device-managed devm_*() helpers, so tear the remaining resources down the same way:
register a devm action that detaches the chained handler, waits for any in-flight handler to finish, disposes of the per-line mappings and removes the IRQ domain. This mirrors the device-managed lifecycle adopted for the GPIO chip and keeps the whole EINT setup self-cleaning on unbind.
--- drivers/pinctrl/mediatek/mtk-eint.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-)
drivers/pinctrl/mediatek/mtk-eint.c +24 -1
@@ -12,8 +12,10 @@*/ #include <linux/delay.h> +#include <linux/device.h> #include <linux/err.h> #include <linux/gpio/driver.h> +#include <linux/interrupt.h> #include <linux/io.h> #include <linux/irqchip/chained_irq.h> #include <linux/irqdomain.h>
@@ -504,6 +506,27 @@ int mtk_eint_find_irq(struct mtk_eint *eint, unsigned long eint_n) }EXPORT_SYMBOL_GPL (mtk_eint_find_irq); +static void mtk_eint_teardown (void *data) +{ +struct mtk_eint *eint = data; +unsigned int i, virq; + +/* Detach the demux handler so it can no longer reference freed data. */ +irq_set_chained_handler_and_data (eint->irq,NULL ,NULL ); + +/* Wait for any in-flight handler to finish before tearing down. */ +synchronize_irq (eint->irq); + +/* Dispose of all child mappings before the domain is removed. */ +for (i =0 ; i < eint->hw->ap_num; i++) { + virq =irq_find_mapping (eint->domain, i); +if (virq) +irq_dispose_mapping (virq); + } + +irq_domain_remove (eint->domain); +} +int mtk_eint_do_init (struct mtk_eint *eint,struct mtk_eint_pin *eint_pin) {unsigned int size, i, port, virq, inst =0 ;
@@ -589,7 +612,7 @@ int mtk_eint_do_init(struct mtk_eint *eint, struct mtk_eint_pin *eint_pin)irq_set_chained_handler_and_data (eint->irq, mtk_eint_irq_handler, eint); -return 0 ; +return devm_add_action_or_reset (eint->dev, mtk_eint_teardown, eint); err_eint:for (i =0 ; i < eint->nbase; i++) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 883/1424 tools/build: Add bpftool-skeletons feature test
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tomas Glozar <[email protected]>
[ Upstream commit 8a635c3856ddb74ed3fe7c856b271cdfeb65f293 ]
Add bpftool-skeletons feature test, testing the presence of a bpftool capable of generating skeletons.
This is to be used for tools that do not require building their own bootstrap bpftool from the kernel source tree.
Stable-dep-of: d5a1d1270c89 ("tools/build: Allow versioning of all LLVM tools defined in Makefile.include")
--- tools/build/Makefile.feature | 3 ++- tools/build/feature/Makefile | 3 +++ tools/scripts/Makefile.include | 3 +++ 3 files changed, 8 insertions(+), 1 deletion(-)
tools/build/Makefile.feature +2 -1
@@ -109,7 +109,8 @@ FEATURE_TESTS_EXTRA := \ libbpf-bpf_create_map \ libpfm4 \ libdebuginfod \ - clang-bpf-co-re + clang-bpf-co-re \ + bpftool-skeletons FEATURE_TESTS ?= $(FEATURE_TESTS_BASIC)
tools/build/feature/Makefile +3 -0
@@ -402,6 +402,9 @@ $(OUTPUT)test-file-handle.bin: $(OUTPUT)test-libpfm4.bin: $(BUILD) -lpfm +$(OUTPUT)test-bpftool-skeletons.bin: + $(BPFTOOL) version | grep '^features:.*skeletons' \ + > $(@:.bin=.make.output) 2>&1 ############################### clean:
tools/scripts/Makefile.include +3 -0
@@ -91,6 +91,9 @@ LLVM_CONFIG ?= llvm-config LLVM_OBJCOPY ?= llvm-objcopy LLVM_STRIP ?= llvm-strip +# Some tools require bpftool +BPFTOOL ?= bpftool + ifeq ($(CC_NO_CLANG), 1) EXTRA_WARNINGS += -Wstrict-aliasing=3
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 884/1424 tools/build: Allow versioning of all LLVM tools defined in Makefile.include
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: James Clark <[email protected]>
[ Upstream commit d5a1d1270c898057afc5b51fb6d0f2defa89d56d ]
The version of LLVM tools can be given on the build command with LLVM=-15, but this isn't applied to all tools. For example $(CC) gets versioned, but $(CLANG) doesn't. This causes a Perf build with LTO=1 to fail with an error about mixed clang versions:
ld.lld: error: libperf/core.o: Unknown attribute kind (86)
(Producer: 'LLVM18.1.8' Reader: 'LLVM 15.0.7')
This file has two "ifneq ($(LLVM),)" blocks adjacent to each other, so merge these blocks making it obvious that all tools should be versioned consistently and there is nothing special about each block.
This also reveals that ?= and "allow-override" are used inconsistently between the blocks. "allow-override" is technically only required for builtin variables, but isn't only used on them, and doesn't do any harm if used on a non-builtin. Make them all "allow-override" for consistency. The only functional difference this will cause is if there is a file level definition of one of the variables followed by an "#include of Makefile.include" which will now overwrite. But this isn't done and in a later commit some of the duplicate definitions will be removed for good measure.
There are also some other LLVM tools that are not defined here and will be moved in a later commit.
--- tools/scripts/Makefile.include | 37 ++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 17 deletions(-)
tools/scripts/Makefile.include +20 -17
@@ -59,10 +59,18 @@ LLVM_SUFFIX := $(LLVM) endif $(call allow-override,CC,$(LLVM_PREFIX)clang$(LLVM_SUFFIX)) +$(call allow-override,CLANG,$(LLVM_PREFIX)clang$(LLVM_SUFFIX)) +$(call allow-override,HOSTCC,$(LLVM_PREFIX)clang$(LLVM_SUFFIX)) $(call allow-override,AR,$(LLVM_PREFIX)llvm-ar$(LLVM_SUFFIX)) +$(call allow-override,HOSTAR,$(LLVM_PREFIX)llvm-ar$(LLVM_SUFFIX)) $(call allow-override,LD,$(LLVM_PREFIX)ld.lld$(LLVM_SUFFIX)) +$(call allow-override,HOSTLD,$(LLVM_PREFIX)ld.lld$(LLVM_SUFFIX)) $(call allow-override,CXX,$(LLVM_PREFIX)clang++$(LLVM_SUFFIX)) $(call allow-override,STRIP,$(LLVM_PREFIX)llvm-strip$(LLVM_SUFFIX)) +$(call allow-override,LLVM_STRIP,$(LLVM_PREFIX)llvm-strip$(LLVM_SUFFIX)) +$(call allow-override,LLC,$(LLVM_PREFIX)llc$(LLVM_SUFFIX)) +$(call allow-override,LLVM_CONFIG,$(LLVM_PREFIX)llvm-config$(LLVM_SUFFIX)) +$(call allow-override,LLVM_OBJCOPY,$(LLVM_PREFIX)llvm-objcopy$(LLVM_SUFFIX)) else # Allow setting various cross-compile vars or setting CROSS_COMPILE as a prefix. $(call allow-override,CC,$(CROSS_COMPILE)gcc)
@@ -70,26 +78,21 @@ $(call allow-override,AR,$(CROSS_COMPILE)ar) $(call allow-override,LD,$(CROSS_COMPILE)ld) $(call allow-override,CXX,$(CROSS_COMPILE)g++) $(call allow-override,STRIP,$(CROSS_COMPILE)strip) -endif - -CC_NO_CLANG := $(shell $(CC) -dM -E -x c /dev/null | grep -Fq "__clang__"; echo $$?) -ifneq ($(LLVM),) -HOSTAR ?= $(LLVM_PREFIX)llvm-ar$(LLVM_SUFFIX) -HOSTCC ?= $(LLVM_PREFIX)clang$(LLVM_SUFFIX) -HOSTLD ?= $(LLVM_PREFIX)ld.lld$(LLVM_SUFFIX) -else -HOSTAR ?= ar -HOSTCC ?= gcc -HOSTLD ?= ld +# Host versions aren't prefixed +$(call allow-override,HOSTAR,ar) +$(call allow-override,HOSTCC,gcc) +$(call allow-override,HOSTLD,ld) + +# Some tools still require Clang, LLC and/or LLVM utils +$(call allow-override,CLANG,clang) +$(call allow-override,LLC,llc) +$(call allow-override,LLVM_CONFIG,llvm-config) +$(call allow-override,LLVM_OBJCOPY,llvm-objcopy) +$(call allow-override,LLVM_STRIP,llvm-strip) endif -# Some tools require Clang, LLC and/or LLVM utils -CLANG ?= clang -LLC ?= llc -LLVM_CONFIG ?= llvm-config -LLVM_OBJCOPY ?= llvm-objcopy -LLVM_STRIP ?= llvm-strip +CC_NO_CLANG := $(shell $(CC) -dM -E -x c /dev/null | grep -Fq "__clang__"; echo $$?) # Some tools require bpftool BPFTOOL ?= bpftool
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 885/1424 power: supply: sbs-battery: Use a per-device serial number buffer
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Babanpreet Singh <[email protected]>
[ Upstream commit 6027892925b8d19d2245c2d077e2ae35b49cc2b1 ]
sbs_get_battery_serial_number() formats the battery serial number into sbs_serial[], a single file-scope buffer shared by every sbs-battery instance, and points val->strval at it.
Nothing restricts this driver to one instance. It binds per I2C client, and sbs-manager registers one muxed I2C channel per supported battery specifically so that the smart battery driver can be bound to each of them, so several sbs-battery instances on one system is a supported configuration.
The power supply core reads strval after the driver's get_property() callback has returned: power_supply_show_property() fills a local union power_supply_propval, then formats it with sysfs_emit(). Two concurrent POWER_SUPPLY_PROP_SERIAL_NUMBER reads on different batteries therefore race for the shared buffer - battery B's sprintf() can land between battery A filling the buffer and the core reading it, and battery A then reports battery B's serial number.
Move the buffer into struct sbs_info so that each battery formats into its own storage. It is deliberately not added to the chip->strings[]
array: those entries hold the cached constant strings that sbs_invalidate_cached_props() clears on presence changes, whereas the serial number is re-read from its word register on every access.
--- drivers/power/supply/sbs-battery.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
drivers/power/supply/sbs-battery.c +4 -3
@@ -216,6 +216,7 @@ struct sbs_info {u32 flags;int technology;char strings[NR_STRING_BUFFERS ][I2C_SMBUS_BLOCK_MAX +1 ]; +char serial[5 ]; }; static char *sbs_get_string_buf(struct sbs_info *chip,
@@ -820,18 +821,18 @@ static int sbs_get_battery_capacity(struct i2c_client *client,return 0 ; } -static char sbs_serial[5 ];static int sbs_get_battery_serial_number (struct i2c_client *client,union power_supply_propval *val) { +struct sbs_info *chip =i2c_get_clientdata (client);int ret; ret =sbs_read_word_data (client, sbs_data[REG_SERIAL_NUMBER ].addr);if (ret <0 )return ret; -sprintf (sbs_serial,"%04x" , ret); - val->strval = sbs_serial; +sprintf (chip->serial,"%04x" , ret); + val->strval = chip->serial;return 0 ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 886/1424 scsi: ufs: debugfs: Reserve space for a string terminator
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Li Qiang <[email protected]>
[ Upstream commit abd26e6b53c4169122d61fdd4cabe09bdd916aac ]
ufs_saved_err_write() copies user input into a zero-initialized stack buffer and passes it to kstrtoint(). A write that fills the entire buffer overwrites its only terminator.
Reject an input whose length leaves no room for the trailing NUL.
--- drivers/ufs/core/ufs-debugfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/ufs/core/ufs-debugfs.c +1 -1
@@ -165,7 +165,7 @@ static ssize_t ufs_saved_err_write(struct file *file, const char __user *buf,char val_str[16 ] = { };int val, ret; -if (count >sizeof (val_str)) +if (count >=sizeof (val_str))return -EINVAL ;if (copy_from_user (val_str, buf, count))return -EFAULT ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 887/1424 crypto: keembay - Initialize completion before requesting IRQ
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Linmao Li <[email protected]>
[ Upstream commit fce20289dd622cc7ab78d72c8a979a9f8b7cb10e ]
kmb_ocs_aes_probe() requests the device IRQ before initializing irq_completion. Once the handler is registered it can run immediately, and ocs_aes_irq_handler() unconditionally calls complete(). An interrupt in this window would therefore use an uninitialized completion.
Initialize the completion before requesting the IRQ, as the sibling OCS HCU and ECC drivers already do.
--- drivers/crypto/intel/keembay/keembay-ocs-aes-core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/crypto/intel/keembay/keembay-ocs-aes-core.c +2 -2
@@ -1604,6 +1604,8 @@ static int kmb_ocs_aes_probe(struct platform_device *pdev)if (IS_ERR (aes_dev->base_reg))return PTR_ERR (aes_dev->base_reg); +init_completion (&aes_dev->irq_completion); +/* Get and request IRQ */ aes_dev->irq =platform_get_irq (pdev,0 );if (aes_dev->irq <0 )
@@ -1621,8 +1623,6 @@ static int kmb_ocs_aes_probe(struct platform_device *pdev)list_add_tail (&aes_dev->list, &ocs_aes.dev_list);spin_unlock (&ocs_aes.lock); -init_completion (&aes_dev->irq_completion); -/* Initialize crypto engine */ aes_dev->engine =crypto_engine_alloc_init (dev, true);if (!aes_dev->engine) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 888/1424 crypto: keembay - publish OF module alias for OCS AES/SM4
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Can Peng <[email protected]>
[ Upstream commit 0a94091e29f914e4f233a208599ca4055882c01b ]
The Keem Bay OCS AES/SM4 driver has an OF match table wired to .of_match_table, but does not export the table with MODULE_DEVICE_TABLE().
Although the match table lives in keembay-ocs-aes-core.o, that object is part of the composite keembay-ocs-aes module. Add the missing MODULE_DEVICE_TABLE(of, ...) entry so modpost can generate OF module alias information for OF based module autoloading.
This is a source-level fix. It does not claim dynamic hardware reproduction; the evidence is the driver-owned match table, its use by the platform driver, and the missing module alias publication.
--- drivers/crypto/intel/keembay/keembay-ocs-aes-core.c | 1 + 1 file changed, 1 insertion(+)
drivers/crypto/intel/keembay/keembay-ocs-aes-core.c +1 -0
@@ -1561,6 +1561,7 @@ static const struct of_device_id kmb_ocs_aes_of_match[] = { }, {} }; +MODULE_DEVICE_TABLE (of, kmb_ocs_aes_of_match);static int kmb_ocs_aes_remove (struct platform_device *pdev) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 889/1424 RDMA/mlx5: Fix integer overflow of user QP buffer size
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Maher Sanalla <[email protected]>
[ Upstream commit dec47e4b0fe34afdf38caa72b4408ba95502e5de ]
set_user_buf_size() computes the QP buffer size by left-shifting the user-supplied rq.wqe_cnt and rq.wqe_shift values as signed integers. A sufficiently large rq.wqe_cnt causes signed integer overflow, which is undefined behavior, and yields a small or negative buf_size, causing ib_umem_get() to map a buffer smaller than the hardware will actually write into.
Replace the shifts and addition with check_shl_overflow() and check_add_overflow(), rejecting invalid user inputs.
Moreover, guard the identical shift computing qp->sq.offset in _create_user_qp() before set_user_buf_size() is reached.
--- drivers/infiniband/hw/mlx5/qp.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-)
drivers/infiniband/hw/mlx5/qp.c +20 -5
@@ -637,6 +637,7 @@ static int set_user_buf_size(struct mlx5_ib_dev *dev, struct ib_qp_init_attr *attr) {int desc_sz =1 << qp->sq.wqe_shift; +int rq_buf_size, sq_buf_size;if (desc_sz >MLX5_CAP_GEN (dev->mdev, max_wqe_sz_sq)) { mlx5_ib_warn(dev, "desc_sz %d, max_sq_desc_sz %d\n",
@@ -661,11 +662,21 @@ static int set_user_buf_size(struct mlx5_ib_dev *dev,if (attr->qp_type ==IB_QPT_RAW_PACKET || qp->flags &IB_QP_CREATE_SOURCE_QPN ) { - base->ubuffer.buf_size = qp->rq.wqe_cnt << qp->rq.wqe_shift; - qp->raw_packet_qp.sq.ubuffer.buf_size = qp->sq.wqe_cnt <<6 ; +if (check_shl_overflow (qp->rq.wqe_cnt, qp->rq.wqe_shift, + &base->ubuffer.buf_size)) +return -EINVAL ; +if (check_shl_overflow (qp->sq.wqe_cnt,6 , + &qp->raw_packet_qp.sq.ubuffer.buf_size)) +return -EINVAL ; }else { - base->ubuffer.buf_size = (qp->rq.wqe_cnt << qp->rq.wqe_shift) + - (qp->sq.wqe_cnt <<6 ); +if (check_shl_overflow (qp->rq.wqe_cnt, qp->rq.wqe_shift, + &rq_buf_size)) +return -EINVAL ; +if (check_shl_overflow (qp->sq.wqe_cnt,6 , &sq_buf_size)) +return -EINVAL ; +if (check_add_overflow (rq_buf_size, sq_buf_size, + &base->ubuffer.buf_size)) +return -EINVAL ; }return 0 ;
@@ -989,7 +1000,11 @@ static int _create_user_qp(struct mlx5_ib_dev *dev, struct ib_pd *pd, qp->rq.offset =0 ; qp->sq.wqe_shift =ilog2 (MLX5_SEND_WQE_BB ); - qp->sq.offset = qp->rq.wqe_cnt << qp->rq.wqe_shift; +if (check_shl_overflow (qp->rq.wqe_cnt, qp->rq.wqe_shift, + &qp->sq.offset)) { + err = -EINVAL ; + goto err_bfreg; + } err =set_user_buf_size (dev, qp, ucmd, base, attr);if (err)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 890/1424 isofs: release zisofs block pointer buffer head
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yichong Chen <[email protected]>
[ Upstream commit 2f7dd9b86fe4076059e6a4a2a2c5d565afd76b9e ]
zisofs_fill_pages() reads the compressed block pointer table. The error paths release the current buffer_head, the loop also releases the old buffer_head when it advances. However, the success path leaves the last buffer_head referenced. Release it before returning success.
--- fs/isofs/compress.c | 1 + 1 file changed, 1 insertion(+)
fs/isofs/compress.c +1 -0
@@ -293,6 +293,7 @@ static int zisofs_fill_pages(struct inode *inode, int full_page, int pcount,memzero_page (*pages, poffset,PAGE_SIZE - poffset);SetPageUptodate (*pages); } +brelse (bh);return 0 ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 891/1424 w1: ds2482: Fix signedness bug in ds2482_w1_triplet()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Babanpreet Singh <[email protected]>
[ Upstream commit 4d3721b204f961e905714954ff95633337b768e3 ]
ds2482_wait_1wire_idle() returns the status register value (0..255) on success, or a negative value on I2C failure: -1 when selecting the status register fails, or a negative errno from i2c_smbus_read_byte().
ds2482_w1_triplet() feeds that result into "return (status >> 5);" without checking for errors, and the function returns u8. For a negative status the arithmetic shift keeps the sign and the u8 truncation fabricates a triplet result whose meaning depends on the errno value: -1 and -EIO happen to become 0xff, whose set low bits make w1_search() abort, but -ETIMEDOUT (-110 >> 5 = -4) becomes 0xfc - "devices responded on both branches, wrote 1" - and -EOPNOTSUPP (-95 >> 5 = -3) becomes 0xfd - "only the zero branch responded". w1_search() then continues the ROM search with a fabricated direction bit instead of aborting, and the corrupted id is either rejected by the ROM CRC (existing device missed) or registers a phantom slave.
The function already defines an in-band error value: status is initialized to (3 << 5), which decodes to 3 (both branch bits set, "no device responded") and makes w1_search() terminate the search when sending the triplet command fails. Decode a negative status to the same value.
Found by smatch:drivers/w1/masters/ds2482.c:314 ds2482_w1_triplet() warn: signedness bug returning '(-67108864)'
--- drivers/w1/masters/ds2482.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/w1/masters/ds2482.c +4 -0
@@ -309,6 +309,10 @@ static u8 ds2482_w1_triplet(void *data, u8 dbit)mutex_unlock (&pdev->access_lock); +/* On bus error, decode to 3 (no device responded) to abort the search */ +if (status <0 ) + status =3 <<5 ; +/* Decode the status */ return (status >>5 ); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 892/1424 remoteproc: core: Drop redundant initialization of ret in rproc_shutdown()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Peng Fan <[email protected]>
[ Upstream commit 4531b6bad5af669511c348ad5225d9f697af221b ]
The variable ret is immediately assigned the return value of mutex_lock_interruptible(), making its prior initialization to zero unnecessary. Remove the redundant assignment
No functional changes.
Stable-dep-of: 2482ca875ef5 ("remoteproc: Allow shutdown of crashed processors")
--- drivers/remoteproc/remoteproc_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/remoteproc/remoteproc_core.c +1 -1
@@ -1988,7 +1988,7 @@ EXPORT_SYMBOL(rproc_boot);int rproc_shutdown (struct rproc *rproc) {struct device *dev = &rproc->dev; -int ret =0 ; +int ret; ret =mutex_lock_interruptible (&rproc->lock);if (ret) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 893/1424 remoteproc: Allow shutdown of crashed processors
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bjorn Andersson <[email protected]>
[ Upstream commit 2482ca875ef5993df8daee563033d70e2523a25f ]
rproc_shutdown() rejects a remoteproc in RPROC_CRASHED state, and rproc_del() ignores that error. The result of these two decisions is that a user cannot stop a remoteproc that with recovery disabled that has entered a crash state, and removal of an associated remoteproc driver will release resources without first stopping the remoteproc.
Allow rproc_shutdown() to stop crashed processors. Propagate the crash state to subdevice teardown, to allow subdevices to dismantle things appropriately.
--- drivers/remoteproc/remoteproc_core.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
drivers/remoteproc/remoteproc_core.c +5 -2
@@ -1988,6 +1988,7 @@ EXPORT_SYMBOL(rproc_boot);int rproc_shutdown (struct rproc *rproc) {struct device *dev = &rproc->dev; +bool crashed;int ret; ret =mutex_lock_interruptible (&rproc->lock);
@@ -1997,16 +1998,18 @@ int rproc_shutdown(struct rproc *rproc) }if (rproc->state !=RPROC_RUNNING && - rproc->state !=RPROC_ATTACHED ) { + rproc->state !=RPROC_ATTACHED && + rproc->state !=RPROC_CRASHED ) { ret = -EINVAL ; goto out; } + crashed = rproc->state ==RPROC_CRASHED ;/* if the remote proc is still needed, bail out */ if (!atomic_dec_and_test (&rproc->power)) goto out; - ret =rproc_stop (rproc, false); + ret =rproc_stop (rproc, crashed);if (ret) {atomic_inc (&rproc->power); goto out;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 894/1424 remoteproc: core: Attach rproc asynchronously in rproc_add() path via schedule_work()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jingyi Wang <[email protected]>
[ Upstream commit 026a3fada43261e403c6c4d9bda9501547e3f108 ]
Unlike the remoteproc firmware load path where rproc_add() call rproc_auto_boot_callback() asynchronously and ignores the return value of rproc_boot(), the attach path calls rproc_boot() synchronously and propagates its return value back to rproc_add(). This means a failure during rproc_attach() causes rproc_add() to fail and triggers resource release, removing the remoteproc from sysfs and making it unavailable for recovery or further boot attempts.
Align the remoteproc attach path with the firmware load path by introducing attach_work and scheduling rproc_boot() asynchronously via schedule_work(). This keeps the remoteproc registered and available in sysfs even if the initial attach attempt fails, and avoids blocking rproc_add() on the attach result.
Stable-dep-of: 74ee3b2f5767 ("remoteproc: Prevent crash handling to race with rproc_del()")
--- drivers/remoteproc/remoteproc_core.c | 20 ++++++++++++-------- include/linux/remoteproc.h | 2 ++ 2 files changed, 14 insertions(+), 8 deletions(-)
drivers/remoteproc/remoteproc_core.c +12 -8
@@ -1677,18 +1677,21 @@ static void rproc_auto_boot_callback(const struct firmware *fw, void *context)release_firmware (fw); } +static void rproc_attach_work (struct work_struct *work) +{ + struct rproc *rproc = container_of(work, struct rproc, attach_work); + +rproc_boot (rproc); +} +static int rproc_trigger_auto_boot (struct rproc *rproc) {int ret; -/* -* Since the remote processor is in a detached state, it has already -* been booted by another entity. As such there is no point in waiting -* for a firmware image to be loaded, we can simply initiate the process -* of attaching to it immediately. -*/ -if (rproc->state ==RPROC_DETACHED ) -return rproc_boot (rproc); +if (rproc->state ==RPROC_DETACHED ) { +schedule_work (&rproc->attach_work); +return 0 ; + }/* * We're initiating an asynchronous firmware loading, so we can
@@ -2500,6 +2503,7 @@ struct rproc *rproc_alloc(struct device *dev, const char *name,INIT_LIST_HEAD (&rproc->dump_segments);INIT_WORK (&rproc->crash_handler, rproc_crash_handler_work); +INIT_WORK (&rproc->attach_work, rproc_attach_work); rproc->state =RPROC_OFFLINE ;
include/linux/remoteproc.h +2 -0
@@ -526,6 +526,7 @@ enum rproc_features {* @subdevs: list of subdevices, to following the running state * @notifyids: idr for dynamically assigning rproc-wide unique notify ids * @index: index of this rproc device +* @attach_work: workqueue for attaching rproc * @crash_handler: workqueue for handling a crash * @crash_cnt: crash counter * @recovery_disabled: flag that state if recovery was disabled
@@ -568,6 +569,7 @@ struct rproc {struct list_head subdevs;struct idr notifyids;int index; +struct work_struct attach_work;struct work_struct crash_handler;unsigned int crash_cnt;bool recovery_disabled;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 895/1424 remoteproc: Prevent crash handling to race with rproc_del()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bjorn Andersson <[email protected]>
[ Upstream commit 74ee3b2f5767447c57959994341e5b95f1079977 ]
There's no synchronization between rproc_crash_handler_work() and rproc_del(), as such it's possible for a driver to be removed while crash-handler work is scheduled, or even executing - resulting in use-after-free issues.
To avoid this the scheduled work need to be cancelled and synchronized against before the removal proceeds.
In order to ensure that this doesn't race with the reporting, and thereby scheduling new work, a "deleting" flag is introduced. This is similar to the RPROC_DELETE state that was introduced to ensure that "start" didn't race with rproc_del(), but the existing mechanism can not be used as it's valid to call rproc_report_crash() in atomic context - and the "state" is protected by a mutex.
In the event that work is cancelled the pm_stay_awake() is left unbalanced and need to be unrolled.
The blocking and cancelling of crash-handler work prior to the actual rproc_shutdown() call does have the explicit side-effect that crashes resulting from the shutdown process will not enter the crash-handling path, and as such will not generate devcoredumps etc. Due to the existing mutual exclusion between these code paths there's no concrete reduction in functionality, but further work would be needed to handle this case.
--- drivers/remoteproc/remoteproc_core.c | 42 +++++++++++++++++++++------ drivers/remoteproc/remoteproc_sysfs.c | 1 - include/linux/remoteproc.h | 13 +++++---- 3 files changed, 41 insertions(+), 15 deletions(-)
drivers/remoteproc/remoteproc_core.c +33 -9
@@ -1840,6 +1840,11 @@ int rproc_trigger_recovery(struct rproc *rproc)if (ret)return ret; +if (READ_ONCE (rproc->deleting)) { + ret = -ENODEV ; + goto unlock_mutex; + } +/* State could have changed before we got the mutex */ if (rproc->state !=RPROC_CRASHED ) goto unlock_mutex;
@@ -1872,6 +1877,11 @@ static void rproc_crash_handler_work(struct work_struct *work)mutex_lock (&rproc->lock); +if (READ_ONCE (rproc->deleting)) { +mutex_unlock (&rproc->lock); + goto out; + } +if (rproc->state ==RPROC_CRASHED ) {/* handle only the first crash detected */ mutex_unlock (&rproc->lock);
@@ -1927,9 +1937,9 @@ int rproc_boot(struct rproc *rproc)return ret; } -if (rproc->state ==RPROC_DELETED ) { +if (READ_ONCE (rproc->deleting)) { ret = -ENODEV ; -dev_err (dev,"can't boot deleted rproc %s\n" , rproc->name); +dev_err (dev,"can't boot deleting rproc %s\n" , rproc->name); goto unlock_mutex; }
@@ -2502,8 +2512,9 @@ struct rproc *rproc_alloc(struct device *dev, const char *name,INIT_LIST_HEAD (&rproc->subdevs);INIT_LIST_HEAD (&rproc->dump_segments); -INIT_WORK (&rproc->crash_handler, rproc_crash_handler_work);INIT_WORK (&rproc->attach_work, rproc_attach_work); +INIT_WORK (&rproc->crash_handler, rproc_crash_handler_work); +spin_lock_init (&rproc->crash_handler_lock); rproc->state =RPROC_OFFLINE ;
@@ -2563,16 +2574,21 @@ EXPORT_SYMBOL(rproc_put);*/ int rproc_del (struct rproc *rproc) { +unsigned long flags; +if (!rproc)return -EINVAL ; +spin_lock_irqsave (&rproc->crash_handler_lock, flags); +WRITE_ONCE (rproc->deleting, true); +spin_unlock_irqrestore (&rproc->crash_handler_lock, flags); + +if (cancel_work_sync (&rproc->crash_handler)) +pm_relax (rproc->dev.parent); +/* TODO: make sure this works with rproc->power > 1 */ rproc_shutdown (rproc); -mutex_lock (&rproc->lock); - rproc->state =RPROC_DELETED ; -mutex_unlock (&rproc->lock); -rproc_delete_debug_dir (rproc);/* the rproc is downref'ed as soon as it's removed from the klist */
@@ -2684,18 +2700,26 @@ EXPORT_SYMBOL(rproc_get_by_child);*/ void rproc_report_crash (struct rproc *rproc,enum rproc_crash_type type) { +unsigned long flags; +if (!rproc) {pr_err ("NULL rproc pointer\n" );return ; } +spin_lock_irqsave (&rproc->crash_handler_lock, flags); +if (READ_ONCE (rproc->deleting)) { +spin_unlock_irqrestore (&rproc->crash_handler_lock, flags); +return ; + } +/* Prevent suspend while the remoteproc is being recovered */ pm_stay_awake (rproc->dev.parent); +queue_work (rproc_recovery_wq, &rproc->crash_handler); +spin_unlock_irqrestore (&rproc->crash_handler_lock, flags);dev_err (&rproc->dev,"crash detected in %s: type %s\n" , rproc->name,rproc_crash_to_string (type)); - -queue_work (rproc_recovery_wq, &rproc->crash_handler); }EXPORT_SYMBOL (rproc_report_crash);
drivers/remoteproc/remoteproc_sysfs.c +0 -1
@@ -168,7 +168,6 @@ static const char * const rproc_state_string[] = { [RPROC_SUSPENDED] = "suspended", [RPROC_RUNNING] = "running", [RPROC_CRASHED] = "crashed", - [RPROC_DELETED] = "deleted", [RPROC_ATTACHED] = "attached", [RPROC_DETACHED] = "detached", [RPROC_LAST] = "invalid",
include/linux/remoteproc.h +8 -5
@@ -37,6 +37,7 @@#include <linux/types.h> #include <linux/mutex.h> +#include <linux/spinlock.h> #include <linux/virtio.h> #include <linux/cdev.h> #include <linux/completion.h>
@@ -412,7 +413,6 @@ struct rproc_ops {* a message. * @RPROC_RUNNING: device is up and running * @RPROC_CRASHED: device has crashed; need to start recovery -* @RPROC_DELETED: device is deleted * @RPROC_ATTACHED: device has been booted by another entity and the core * has attached to it * @RPROC_DETACHED: device has been booted by another entity and waiting
@@ -430,10 +430,9 @@ enum rproc_state {RPROC_SUSPENDED =1 ,RPROC_RUNNING =2 ,RPROC_CRASHED =3 , -RPROC_DELETED =4 , -RPROC_ATTACHED =5 , -RPROC_DETACHED =6 , - RPROC_LAST = 7, +RPROC_ATTACHED =4 , +RPROC_DETACHED =5 , + RPROC_LAST = 6, };/**
@@ -528,6 +527,8 @@ enum rproc_features {* @index: index of this rproc device * @attach_work: workqueue for attaching rproc * @crash_handler: workqueue for handling a crash +* @crash_handler_lock: serializes crash handler queueing and deletion +* @deleting: remoteproc deletion has begun * @crash_cnt: crash counter * @recovery_disabled: flag that state if recovery was disabled * @max_notifyid: largest allocated notify id.
@@ -571,6 +572,8 @@ struct rproc {int index;struct work_struct attach_work;struct work_struct crash_handler; +spinlock_t crash_handler_lock; +bool deleting;unsigned int crash_cnt;bool recovery_disabled;int max_notifyid;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 896/1424 staging: rtl8723bs: use kfree_sensitive() for key material
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ivy Lopez <[email protected]>
[ Upstream commit d205dfa8cb825f1954ca1cfa474fc50bf06ee4aa ]
The set_stakey_parm struct contains a 16-byte encryption key. Use kfree_sensitive() instead of kfree() to ensure the key material is zeroed before the memory is freed, preventing potential information leaks.
--- drivers/staging/rtl8723bs/core/rtw_cmd.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/staging/rtl8723bs/core/rtw_cmd.c +4 -4
@@ -895,7 +895,7 @@ u8 rtw_setstakey_cmd(struct adapter *padapter, struct sta_info *sta, u8 unicast_if (enqueue) { ph2c =rtw_zmalloc (sizeof (struct cmd_obj ));if (!ph2c) { -kfree (psetstakey_para); +kfree_sensitive (psetstakey_para); res = _FAIL; goto exit; }
@@ -903,7 +903,7 @@ u8 rtw_setstakey_cmd(struct adapter *padapter, struct sta_info *sta, u8 unicast_ psetstakey_rsp =rtw_zmalloc (sizeof (struct set_stakey_rsp ));if (!psetstakey_rsp) {kfree (ph2c); -kfree (psetstakey_para); +kfree_sensitive (psetstakey_para); res = _FAIL; goto exit; }
@@ -914,7 +914,7 @@ u8 rtw_setstakey_cmd(struct adapter *padapter, struct sta_info *sta, u8 unicast_ res =rtw_enqueue_cmd (pcmdpriv, ph2c); }else {set_stakey_hdl (padapter, (u8 *)psetstakey_para); -kfree (psetstakey_para); +kfree_sensitive (psetstakey_para); } exit:return res;
@@ -954,7 +954,7 @@ u8 rtw_clearstakey_cmd(struct adapter *padapter, struct sta_info *sta, u8 enqueu psetstakey_rsp =rtw_zmalloc (sizeof (struct set_stakey_rsp ));if (!psetstakey_rsp) {kfree (ph2c); -kfree (psetstakey_para); +kfree_sensitive (psetstakey_para); res = _FAIL; goto exit; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 897/1424 fs/ntfs3: reject restart table growth beyond U16_MAX entries
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Weiming Shi <[email protected]>
[ Upstream commit 111f8d74a19d85942ecbb3aba78f6f3c88e59391 ]
During $LogFile replay, log_replay() indexes the transaction table by the transact_id taken from the log record header. check_log_rec() only verifies that transact_id is non-zero and properly aligned, not its magnitude, so a crafted image can request an arbitrarily large index.
alloc_rsttbl_from_idx() grows the table to cover that index via extend_rsttbl(), which passes the new entry count to init_rsttbl():
rt = init_rsttbl(esize, used + add);
used + add is computed as u32 but init_rsttbl() takes a u16, and the count is stored in struct RESTART_TABLE as a __le16. When used + add exceeds U16_MAX it is truncated, init_rsttbl() allocates a table far smaller than the index requires, and alloc_rsttbl_from_idx() then dereferences and writes at the original, untruncated offset -- an out-of-bounds access past the allocation, reachable by mounting a crafted NTFS image.
BUG: KASAN: use-after-free in alloc_rsttbl_from_idx (fs/ntfs3/fslog.c:950) Read of size 4 at addr ffff8880327ffff8 by task exploit alloc_rsttbl_from_idx (fs/ntfs3/fslog.c:950) log_replay (fs/ntfs3/fslog.c:4562) ntfs_loadlog_and_replay (fs/ntfs3/fsntfs.c:324) ntfs_fill_super (fs/ntfs3/super.c:1393) get_tree_bdev_flags vfs_get_tree path_mount __x64_sys_mount
A restart table is limited to U16_MAX entries by its __le16 count, so a larger growth request is invalid input. Reject it in extend_rsttbl(); all callers already handle a NULL return.
--- fs/ntfs3/fslog.c | 3 +++ 1 file changed, 3 insertions(+)
fs/ntfs3/fslog.c +3 -0
@@ -875,6 +875,9 @@ static inline struct RESTART_TABLE *extend_rsttbl(struct RESTART_TABLE *tbl,u32 used =le16_to_cpu (tbl->used);struct RESTART_TABLE *rt; +if (used + add >U16_MAX ) +return NULL ; + rt =init_rsttbl (esize, used + add);if (!rt)return NULL ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 898/1424 RDMA/efa: Fix PBL chunk length computation
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yonatan Nachum <[email protected]>
[ Upstream commit 229b42d7450c1cf96f45ec39ebb69211b06bc036 ]
On register MR, when creating the PBL, if it's an indirect PBL we create a chunk list to hold the PBL pages pointers. Each chunk is 4KB in size and can hold 510 addresses (EFA_PTRS_PER_CHUNK) and has a 12-byte control buffer at the end of it holding the next chunk's pointer and its length.
If the PBL number of pages is a multiple of EFA_PTRS_PER_CHUNK, the calculated last chunk length is wrongly computed as 0, even though that chunk is fully populated with 510 real page pointers. This wrong length is used both to DMA map the chunk and is propagated to the device, causing the device to see the chunk as empty and reject the memory registration.
Fix the calculation so it will be performed only if the number of pages isn't a multiple of EFA_PTRS_PER_CHUNK, if it is, its already handled in the above loop correctly.
Also prevent out-of-bounds reach in the chunks array in such scenario.
--- drivers/infiniband/hw/efa/efa_verbs.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-)
drivers/infiniband/hw/efa/efa_verbs.c +9 -4
@@ -1296,9 +1296,11 @@ static int pbl_chunk_list_create(struct efa_dev *dev, struct pbl_context *pbl) chunk_list->chunks[i].length =EFA_CHUNK_USED_SIZE ; } - chunk_list->chunks[chunk_list_size -1 ].length = - ((page_cnt %EFA_PTRS_PER_CHUNK ) *EFA_CHUNK_PAYLOAD_PTR_SIZE ) + -EFA_CHUNK_PTR_SIZE ; + +if (page_cnt %EFA_PTRS_PER_CHUNK !=0 ) + chunk_list->chunks[chunk_list_size -1 ].length = + ((page_cnt %EFA_PTRS_PER_CHUNK ) *EFA_CHUNK_PAYLOAD_PTR_SIZE ) + +EFA_CHUNK_PTR_SIZE ;/* fill the dma addresses of sg list pages to chunks: */ chunk_idx =0 ;
@@ -1310,9 +1312,12 @@ static int pbl_chunk_list_create(struct efa_dev *dev, struct pbl_context *pbl)rdma_block_iter_dma_address (&biter);if (payload_idx ==EFA_PTRS_PER_CHUNK ) { + payload_idx =0 ; chunk_idx++; +if (chunk_idx >= chunk_list_size) +break ; + cur_chunk_buf = chunk_list->chunks[chunk_idx].buf; - payload_idx =0 ; } }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 899/1424 arm64: dts: allwinner: sun50i-a64-pinephone: Fix mpu6050 mount matrix
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ondrej Jirman <[email protected]>
[ Upstream commit dfc735fd93e4814e65894916ec5f807f25a391d1 ]
The current mount matrix for mpu6050 is wrong. The mount matrix is a simple transform from the sensor coordinate space to the device coordinate space described in DT, where, looking at the screen, X points to the right, Y to the top, and Z towards the user.
The mpu6050 is mounted like this (looking at the screen from the front; the sensor is on the near side of the PCB, so its Z axis points towards the user; o marks the pin 1 corner):
+Xs
^
|
+------+
+Ys <--| |
| o |
+------+so this gives:
Xd = -Ys [0, -1, 0] Yd = Xs [1, 0, 0] Zd = Zs [0, 0, 1]
--- arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi +2 -2
@@ -202,8 +202,8 @@ accelerometer@68 { interrupts = <7 5 IRQ_TYPE_EDGE_RISING>; /* PH5 */ vdd-supply = <®_dldo1>; vddio-supply = <®_dldo1>; - mount-matrix = "0", "1", "0", - "-1", "0", "0", + mount-matrix = "0", "-1", "0", + "1", "0", "0", "0", "0", "1"; }; };
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 900/1424 clk: tegra: tegra124-emc: put EMC node on register failure
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guangshuo Li <[email protected]>
[ Upstream commit f726279f5eab813f9a8b6f38ddf2a4b062d038ff ]
tegra124_clk_register_emc() stores a device node reference returned by of_parse_phandle() in tegra->emc_node.
If clk_register() fails, the function returns an error before that reference can be consumed and released by the normal runtime path. The tegra_clk_emc object is freed on this failure path, but freeing the object does not drop the OF node reference stored in it.
Drop the EMC node reference before freeing the tegra_clk_emc object. of_node_put() is safe for a NULL node, so this also covers the case where the phandle is absent.
--- drivers/clk/tegra/clk-tegra124-emc.c | 1 + 1 file changed, 1 insertion(+)
drivers/clk/tegra/clk-tegra124-emc.c +1 -0
@@ -539,6 +539,7 @@ struct clk *tegra124_clk_register_emc(void __iomem *base, struct device_node *np clk =clk_register (NULL , &tegra->hw);if (IS_ERR (clk)) { +of_node_put (tegra->emc_node);kfree (tegra);return clk; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 901/1424 clk: palmas: Manage external-control prepare with devm
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Myeonghun Pak <[email protected]>
[ Upstream commit ccda84fcbf3a972973f772384935928f41817b3a ]
palmas_clks_init_configure() prepares the clock when an external control pin is configured. The current driver only drops that prepare reference when external control configuration fails.
If provider registration fails after that point, or if the driver is later removed, the prepare reference remains held.
Register a device-managed action after clk_prepare() succeeds. This balances the prepare reference on subsequent probe failure and driver removal.
--- drivers/clk/clk-palmas.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-)
drivers/clk/clk-palmas.c +13 -1
@@ -194,6 +194,13 @@ static void palmas_clks_get_clk_data(struct platform_device *pdev, cinfo->ext_control_pin = prop; } +static void palmas_clks_unprepare_ext_control (void *data) +{ +struct palmas_clock_info *cinfo = data; + +clk_unprepare (cinfo->hw.clk); +} +static int palmas_clks_init_configure (struct palmas_clock_info *cinfo) {int ret;
@@ -214,13 +221,18 @@ static int palmas_clks_init_configure(struct palmas_clock_info *cinfo)return ret; } + ret =devm_add_action_or_reset (cinfo->dev, + palmas_clks_unprepare_ext_control, + cinfo); +if (ret) +return ret; + ret =palmas_ext_control_req_config (cinfo->palmas, cinfo->clk_desc->sleep_reqstr_id, cinfo->ext_control_pin, true);if (ret <0 ) {dev_err (cinfo->dev,"Ext config for %s failed, %d\n" , cinfo->clk_desc->clk_name, ret); -clk_unprepare (cinfo->hw.clk);return ret; } }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 902/1424 clk/x86: pmc_atom: add kasprintf return value check
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: longlong yan <[email protected]>
[ Upstream commit 18e9d14cbac33db1c1fb933c26a736eef53dd538 ]
The kasprintf() function returns NULL on memory allocation failure, but the code in plt_clk_register() was not checking this return value. If kasprintf fails, init.name would be NULL and could cause NULL pointer dereference when clkdev_hw_create() uses it.
Add proper error checking for the kasprintf() return value and return ERR_PTR(-ENOMEM) on failure.
--- drivers/clk/x86/clk-pmc-atom.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/clk/x86/clk-pmc-atom.c +3 -0
@@ -171,6 +171,9 @@ static struct clk_plt *plt_clk_register(struct platform_device *pdev, int id,return ERR_PTR (-ENOMEM ); init.name =kasprintf (GFP_KERNEL ,"%s_%d" ,PLT_CLK_NAME_BASE , id); +if (!init.name) +return ERR_PTR (-ENOMEM ); + init.ops = &plt_clk_ops; init.flags =0 ; init.parent_names = parent_names;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 903/1424 clk: mediatek: mt8135: Fix inverted gate control for devapc_ck
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Akari Tsuyukusa <[email protected]>
[ Upstream commit fd0e3e4edea6a3e4da91be608ca2fb9b348f9e32 ]
The devapc_ck (CLK_INFRA_DEVAPC) on MT8135 is currently using "mtk_clk_gate_ops_setclr". However, checking the downstream kernel reveals that this clock is configured with set:enable and clr:disable making "mtk_clk_gate_ops_setclr_inv" the appropriate choice.
But, it is strange that some downstream kernels are not like that.
Amazon: INV
ChromiumOS (early): not INV
ChromiumOS 3.16 to 3.18-revew-v2: INV
ChromiumOS 3.18-review-v3 and later (sent to kernel.org): not INV
--- drivers/clk/mediatek/clk-mt8135.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/clk/mediatek/clk-mt8135.c +4 -1
@@ -409,6 +409,9 @@ static const struct mtk_gate_regs infra_cg_regs = {GATE_MTK_FLAGS (_id, _name, _parent, &infra_cg_regs, _shift, \ &mtk_clk_gate_ops_setclr, CLK_IS_CRITICAL) +#define GATE_ICG_INV (_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &infra_cg_regs, _shift, &mtk_clk_gate_ops_setclr_inv) +static const struct mtk_gate infra_clks[] = {GATE_DUMMY (CLK_DUMMY ,"infra_dummy" ),GATE_ICG (CLK_INFRA_PMIC_WRAP ,"pmic_wrap_ck" ,"axi_sel" ,23 ),
@@ -419,7 +422,7 @@ static const struct mtk_gate infra_clks[] = {GATE_ICG (CLK_INFRA_CPUM ,"cpum_ck" ,"cpum_tck_in" ,15 ),GATE_ICG_AO (CLK_INFRA_M4U ,"m4u_ck" ,"mem_sel" ,8 ),GATE_ICG (CLK_INFRA_MFGAXI ,"mfgaxi_ck" ,"axi_sel" ,7 ), -GATE_ICG (CLK_INFRA_DEVAPC ,"devapc_ck" ,"axi_sel" ,6 ), +GATE_ICG_INV (CLK_INFRA_DEVAPC ,"devapc_ck" ,"axi_sel" ,6 ),GATE_ICG (CLK_INFRA_AUDIO ,"audio_ck" ,"aud_intbus_sel" ,5 ),GATE_ICG (CLK_INFRA_MFG_BUS ,"mfg_bus_ck" ,"axi_sel" ,2 ), GATE_ICG(CLK_INFRA_SMI, "smi_ck", "smi_sel", 1),
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 904/1424 clk: rockchip: Fix the fractional part denominator on RK3588/RK3576 PLLs
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexey Charkov <[email protected]>
[ Upstream commit 52aef653c3d0c24013dfa9eccf692594eacdbe17 ]
According to the TRM, the fractional PLL coefficient should be divided by 65536 rather than 65535 to obtain the output rate.
Fix the denominator and add a comment with the TRM provided clock formulae for future reference.
See RK3576 TRM Part 1 V1.2 section 2.13.1.4 Setting Guide on P, M, S and K or equivalently RK3588 TRM part 1 V1.0 section 2.17.1.4 Setting Guide on P, M, S and K.
Fractional PLL rates don't seem to be used by any current mainline consumers, so this is purely a correctness fix. It will also be important to properly support DisplayPort output going forward, as the video output controller derives its pixel clock from system PLLs with no dedicated PHY PLL option for DP unlike HDMI, and some display modes are only achievable with fractional PLL rates.
--- drivers/clk/rockchip/clk-pll.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
drivers/clk/rockchip/clk-pll.c +8 -1
@@ -893,6 +893,13 @@ static void rockchip_rk3588_pll_get_params(struct rockchip_clk_pll *pll, rate->k = ((pllcon >>RK3588_PLLCON2_K_SHIFT ) &RK3588_PLLCON2_K_MASK ); } +/* +* 2250 MHz <= Fvco <= 4500 MHz +* For Fvco > 3 GHz: period jitter +-1% frac PLL, +-0.75% int PLL +* For Fvco < 3 GHz: period jitter +-2% frac PLL, +-1.50% int PLL +* Fvco = ((m + k / 65536) * Fin) / p +* Fout = ((m + k / 65536) * Fin) / (p * 2^s) +*/ static unsigned long rockchip_rk3588_pll_recalc_rate (struct clk_hw *hw,unsigned long prate) {struct rockchip_clk_pll *pll =to_rockchip_clk_pll (hw);
@@ -908,7 +915,7 @@ static unsigned long rockchip_rk3588_pll_recalc_rate(struct clk_hw *hw, unsigned/* fractional mode */ u64 frac_rate64 = prate * cur.k; - postdiv = cur.p *65535 ; + postdiv = cur.p *65536 ;do_div (frac_rate64, postdiv); rate64 += frac_rate64; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 905/1424 nilfs2: fix infinite loop in nilfs_clean_segments()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Joshua Crofts <[email protected]>
[ Upstream commit ce5a5ad1a8330a2fcfdd9ec2ab341be739e89a18 ]
syzbot reported a hung task in nilfs_transaction_begin(). This occurs because the cleaner ioctl falls into an infinite loop if nilfs_segctor_construct() repeatedly returns -EROFS (e.g. the device is remounted as read-only after an I/O error).
Currently in nilfs_clean_segments(), if err is non-zero, it logs the error and sleeps but doesn't abort when it encounters a terminal error like -EROFS. This causes the thread to loop forever.
Fix this by breaking out of the loop if nilfs_segctor_construct() returns -EROFS. This matches the behaviour in nilfs_segctor_write_out(), which also handles -EROFS.
--- fs/nilfs2/segment.c | 4 ++++ 1 file changed, 4 insertions(+)
fs/nilfs2/segment.c +4 -0
@@ -2553,6 +2553,10 @@ int nilfs_clean_segments(struct super_block *sb, struct nilfs_argv *argv,break ;nilfs_warn (sb,"error %d cleaning segments" , err); + +if (unlikely (err == -EROFS )) + goto out_unlock; +set_current_state (TASK_INTERRUPTIBLE );schedule_timeout (sci->sc_interval); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 906/1424 nilfs2: prevent out-of-bounds read in super root block parsing
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Lee <[email protected]>
[ Upstream commit 7cb2f76a6a2ba2130b577cb8ac13e1e46c4fc689 ]
super-root inode metadata size is trusted before nilfs_read_inode_common().
Reject super-root inode sizes whose computed on-disk footprint exceeds the filesystem block size. This prevents malformed filesystem images from making nilfs_read_inode_common() read past the end of the super-root block.
[ryusuke: clarify the commit title]
--- fs/nilfs2/the_nilfs.c | 6 ++++++ 1 file changed, 6 insertions(+)
fs/nilfs2/the_nilfs.c +6 -0
@@ -450,6 +450,12 @@ static int nilfs_store_disk_layout(struct the_nilfs *nilfs, nilfs->ns_inode_size);return -EINVAL ; } +if (NILFS_SR_BYTES (nilfs->ns_inode_size) > nilfs->ns_blocksize) { +nilfs_err (nilfs->ns_sb, +"too large inode size for super root: %d bytes" , + nilfs->ns_inode_size); +return -EINVAL ; + } nilfs->ns_first_ino =le32_to_cpu (sbp->s_first_ino);if (nilfs->ns_first_ino <NILFS_USER_INO ) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 907/1424 nilfs2: add nilfs_end_folio_io()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthew Wilcox (Oracle) <[email protected]>
[ Upstream commit 8f46eaf6fd8454b0621b4ce07df50b2aa471c880 ]
Patch series "nilfs2: Folio conversions for file paths".
This series advances page->folio conversions for a wide range of nilfs2, including its file operations, block routines, and the log writer's writeback routines. It doesn't cover large folios support, but it saves a lot of hidden compound_head() calls while preserving the existing support range behavior.
The original series in post [1] also covered directory-related page->folio conversions, but that was put on hold because a regression was found in testing, so this is an excerpt from the first half of the original post.
[1] https://lkml.kernel.org/r/[email protected]
I tested this series in both 32-bit and 64-bit environments, switching between normal and small block sizes. I also reviewed all changes in all patches to ensure they do not break existing behavior. There were no problems.
This patch (of 20):
This is the folio counterpart of the existing nilfs_end_page_io() which is retained as a wrapper of nilfs_end_folio_io(). Replaces nine hidden calls to compound_head() with one.
Stable-dep-of: 66f4ad3ce158 ("nilfs2: fix BUG in nilfs_copy_dirty_pages() on dirty state mismatch")
--- fs/nilfs2/segment.c | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-)
fs/nilfs2/segment.c +22 -14
@@ -1744,17 +1744,18 @@ static int nilfs_segctor_write(struct nilfs_sc_info *sci,return ret; } -static void nilfs_end_page_io (struct page *page,int err) +static void nilfs_end_folio_io (struct folio *folio,int err) { -if (!page) +if (!folio)return ; -if (buffer_nilfs_node (page_buffers (page)) && !PageWriteback (page)) { +if (buffer_nilfs_node (folio_buffers (folio)) && + !folio_test_writeback (folio)) {/* * For b-tree node pages, this function may be called twice * or more because they might be split in a segment. */ -if (PageDirty (page)) { +if (folio_test_dirty (folio)) {/* * For pages holding split b-tree node buffers, dirty * flag on the buffers may be cleared discretely.
@@ -1762,24 +1763,31 @@ static void nilfs_end_page_io(struct page *page, int err)* remaining buffers, and it must be cancelled if * all the buffers get cleaned later. */ -lock_page (page); -if (nilfs_page_buffers_clean (page)) -__nilfs_clear_page_dirty (page); -unlock_page (page); +folio_lock (folio); +if (nilfs_page_buffers_clean (&folio->page)) +__nilfs_clear_page_dirty (&folio->page); +folio_unlock (folio); }return ; }if (!err) { -if (!nilfs_page_buffers_clean (page)) -__set_page_dirty_nobuffers (page); -ClearPageError (page); +if (!nilfs_page_buffers_clean (&folio->page)) +filemap_dirty_folio (folio->mapping, folio); +folio_clear_error (folio); }else { -__set_page_dirty_nobuffers (page); -SetPageError (page); +filemap_dirty_folio (folio->mapping, folio); +folio_set_error (folio); } -end_page_writeback (page); +folio_end_writeback (folio); +} + +static void nilfs_end_page_io (struct page *page,int err) +{ +if (!page) +return ; +nilfs_end_folio_io (page_folio (page), err); }static void nilfs_abort_logs (struct list_head *logs,int err)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 908/1424 nilfs2: convert nilfs_forget_buffer to use a folio
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthew Wilcox (Oracle) <[email protected]>
[ Upstream commit 797e25ad106b5f0c49bdbeb6ce015acae6b93b3b ]
Save two hidden calls to compound_head().
Stable-dep-of: 66f4ad3ce158 ("nilfs2: fix BUG in nilfs_copy_dirty_pages() on dirty state mismatch")
--- fs/nilfs2/page.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
fs/nilfs2/page.c +5 -5
@@ -73,7 +73,7 @@ struct buffer_head *nilfs_grab_buffer(struct inode *inode,*/ void nilfs_forget_buffer (struct buffer_head *bh) { -struct page *page = bh->b_page; +struct folio *folio = bh->b_folio; const unsigned long clear_bits = (BIT(BH_Uptodate) | BIT(BH_Dirty) | BIT(BH_Mapped) | BIT(BH_Async_Write) | BIT(BH_NILFS_Volatile) |
@@ -82,12 +82,12 @@ void nilfs_forget_buffer(struct buffer_head *bh)lock_buffer (bh);set_mask_bits (&bh->b_state, clear_bits,0 ); -if (nilfs_page_buffers_clean (page)) -__nilfs_clear_page_dirty (page); +if (nilfs_page_buffers_clean (&folio->page)) +__nilfs_clear_page_dirty (&folio->page); bh->b_blocknr =-1 ; -ClearPageUptodate (page); -ClearPageMappedToDisk (page); +folio_clear_uptodate (folio); +folio_clear_mappedtodisk (folio);unlock_buffer (bh);brelse (bh); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 909/1424 nilfs2: convert to nilfs_folio_buffers_clean()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthew Wilcox (Oracle) <[email protected]>
[ Upstream commit 36319c0c1c6c4374949f7351a018aa922fb6ef3d ]
All callers of nilfs_page_buffers_clean() now have a folio, so convert it to take a folio. While I'm at it, make it return a bool.
Stable-dep-of: 66f4ad3ce158 ("nilfs2: fix BUG in nilfs_copy_dirty_pages() on dirty state mismatch")
--- fs/nilfs2/page.c | 18 +++++++++--------- fs/nilfs2/page.h | 2 +- fs/nilfs2/segment.c | 4 ++-- 3 files changed, 12 insertions(+), 12 deletions(-)
fs/nilfs2/page.c +9 -9
@@ -82,7 +82,7 @@ void nilfs_forget_buffer(struct buffer_head *bh)lock_buffer (bh);set_mask_bits (&bh->b_state, clear_bits,0 ); -if (nilfs_page_buffers_clean (&folio->page)) +if (nilfs_folio_buffers_clean (folio))__nilfs_clear_page_dirty (&folio->page); bh->b_blocknr =-1 ;
@@ -132,23 +132,23 @@ void nilfs_copy_buffer(struct buffer_head *dbh, struct buffer_head *sbh) }/** -* nilfs_page_buffers_clean - check if a page has dirty buffers or not. -* @page: page to be checked +* nilfs_folio_buffers_clean - Check if a folio has dirty buffers or not. +* @folio: Folio to be checked. * -* nilfs_page_buffers_clean() returns zero if the page has dirty buffers. -* Otherwise, it returns non-zero value. +* nilfs_folio_buffers_clean() returns false if the folio has dirty buffers. +* Otherwise, it returns true. */ -int nilfs_page_buffers_clean (struct page *page) +bool nilfs_folio_buffers_clean (struct folio *folio) {struct buffer_head *bh, *head; - bh = head =page_buffers (page); + bh = head =folio_buffers (folio);do {if (buffer_dirty (bh)) -return 0 ; +return false; bh = bh->b_this_page; }while (bh != head); -return 1 ; +return true; }void nilfs_page_bug (struct page *page)
fs/nilfs2/page.h +1 -1
@@ -36,7 +36,7 @@ struct buffer_head *nilfs_grab_buffer(struct inode *, struct address_space *, unsigned long, unsigned long);void nilfs_forget_buffer (struct buffer_head *);void nilfs_copy_buffer (struct buffer_head *,struct buffer_head *); -int nilfs_page_buffers_clean (struct page *); +bool nilfs_folio_buffers_clean (struct folio *);void nilfs_page_bug (struct page *);int nilfs_copy_dirty_pages (struct address_space *,struct address_space *);
fs/nilfs2/segment.c +2 -2
@@ -1764,7 +1764,7 @@ static void nilfs_end_folio_io(struct folio *folio, int err)* all the buffers get cleaned later. */ folio_lock (folio); -if (nilfs_page_buffers_clean (&folio->page)) +if (nilfs_folio_buffers_clean (folio))__nilfs_clear_page_dirty (&folio->page);folio_unlock (folio); }
@@ -1772,7 +1772,7 @@ static void nilfs_end_folio_io(struct folio *folio, int err) }if (!err) { -if (!nilfs_page_buffers_clean (&folio->page)) +if (!nilfs_folio_buffers_clean (folio))filemap_dirty_folio (folio->mapping, folio);folio_clear_error (folio); }else {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 910/1424 nilfs2: convert nilfs_btnode_prepare_change_key to use a folio
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthew Wilcox (Oracle) <[email protected]>
[ Upstream commit 7c5c654c09c3d08ed04fb19ff0798784027eb33a ]
Saves three calls to compound_head().
Stable-dep-of: 66f4ad3ce158 ("nilfs2: fix BUG in nilfs_copy_dirty_pages() on dirty state mismatch")
--- fs/nilfs2/btnode.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-)
fs/nilfs2/btnode.c +9 -9
@@ -199,23 +199,23 @@ int nilfs_btnode_prepare_change_key(struct address_space *btnc, ctxt->newbh =NULL ;if (inode->i_blkbits ==PAGE_SHIFT ) { -struct page *opage = obh->b_page; -lock_page (opage); +struct folio *ofolio = obh->b_folio; +folio_lock (ofolio); retry:/* BUG_ON(oldkey != obh->b_folio->index); */ -if (unlikely (oldkey != opage->index)) -NILFS_PAGE_BUG (opage, +if (unlikely (oldkey != ofolio->index)) +NILFS_PAGE_BUG (&ofolio->page,"invalid oldkey %lld (newkey=%lld)" , (unsigned long long )oldkey, (unsigned long long )newkey);xa_lock_irq (&btnc->i_pages); - err =__xa_insert (&btnc->i_pages, newkey, opage,GFP_NOFS ); + err =__xa_insert (&btnc->i_pages, newkey, ofolio,GFP_NOFS );xa_unlock_irq (&btnc->i_pages);/* -* Note: page->index will not change to newkey until +* Note: folio->index will not change to newkey until * nilfs_btnode_commit_change_key() will be called. -* To protect the page in intermediate state, the page lock +* To protect the folio in intermediate state, the folio lock * is held. */ if (!err)
@@ -227,7 +227,7 @@ int nilfs_btnode_prepare_change_key(struct address_space *btnc,if (!err) goto retry;/* fallback to copy mode */ -unlock_page (opage); +folio_unlock (ofolio); } nbh =nilfs_btnode_create_block (btnc, newkey);
@@ -239,7 +239,7 @@ int nilfs_btnode_prepare_change_key(struct address_space *btnc,return 0 ; failed_unlock: -unlock_page (obh->b_page); +folio_unlock (obh->b_folio);return err; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 911/1424 nilfs2: convert nilfs_btnode_commit_change_key to use a folio
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthew Wilcox (Oracle) <[email protected]>
[ Upstream commit c2a491f3d88a7d94fed070fe48c859dfc5c9d47c ]
Saves one call to compound_head().
Stable-dep-of: 66f4ad3ce158 ("nilfs2: fix BUG in nilfs_copy_dirty_pages() on dirty state mismatch")
--- fs/nilfs2/btnode.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
fs/nilfs2/btnode.c +6 -6
@@ -252,15 +252,15 @@ void nilfs_btnode_commit_change_key(struct address_space *btnc, {struct buffer_head *obh = ctxt->bh, *nbh = ctxt->newbh;__u64 oldkey = ctxt->oldkey, newkey = ctxt->newkey; -struct page *opage; +struct folio *ofolio;if (oldkey == newkey)return ;if (nbh ==NULL ) {/* blocksize == pagesize */ - opage = obh->b_page; -if (unlikely (oldkey != opage->index)) -NILFS_PAGE_BUG (opage, + ofolio = obh->b_folio; +if (unlikely (oldkey != ofolio->index)) +NILFS_PAGE_BUG (&ofolio->page,"invalid oldkey %lld (newkey=%lld)" , (unsigned long long )oldkey, (unsigned long long )newkey);
@@ -271,8 +271,8 @@ void nilfs_btnode_commit_change_key(struct address_space *btnc,__xa_set_mark (&btnc->i_pages, newkey,PAGECACHE_TAG_DIRTY );xa_unlock_irq (&btnc->i_pages); - opage->index = obh->b_blocknr = newkey; -unlock_page (opage); + ofolio->index = obh->b_blocknr = newkey; +folio_unlock (ofolio); }else {nilfs_copy_buffer (nbh, obh);mark_buffer_dirty (nbh);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 912/1424 nilfs2: convert nilfs_page_bug() to nilfs_folio_bug()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthew Wilcox (Oracle) <[email protected]>
[ Upstream commit b4f19e3bce903712e347ce7f88d0c4f6e43277f9 ]
All callers have a folio now, so convert it.
Stable-dep-of: 66f4ad3ce158 ("nilfs2: fix BUG in nilfs_copy_dirty_pages() on dirty state mismatch")
--- fs/nilfs2/btnode.c | 4 ++-- fs/nilfs2/page.c | 25 +++++++++++++------------ fs/nilfs2/page.h | 6 +++--- 3 files changed, 18 insertions(+), 17 deletions(-)
fs/nilfs2/btnode.c +2 -2
@@ -204,7 +204,7 @@ int nilfs_btnode_prepare_change_key(struct address_space *btnc, retry:/* BUG_ON(oldkey != obh->b_folio->index); */ if (unlikely (oldkey != ofolio->index)) -NILFS_PAGE_BUG (&ofolio->page, +NILFS_FOLIO_BUG (ofolio,"invalid oldkey %lld (newkey=%lld)" , (unsigned long long )oldkey, (unsigned long long )newkey);
@@ -260,7 +260,7 @@ void nilfs_btnode_commit_change_key(struct address_space *btnc,if (nbh ==NULL ) {/* blocksize == pagesize */ ofolio = obh->b_folio;if (unlikely (oldkey != ofolio->index)) -NILFS_PAGE_BUG (&ofolio->page, +NILFS_FOLIO_BUG (ofolio,"invalid oldkey %lld (newkey=%lld)" , (unsigned long long )oldkey, (unsigned long long )newkey);
fs/nilfs2/page.c +13 -12
@@ -151,29 +151,30 @@ bool nilfs_folio_buffers_clean(struct folio *folio)return true; } -void nilfs_page_bug(struct page *page) +void nilfs_folio_bug(struct folio *folio) { + struct buffer_head *bh, *head; struct address_space *m; unsigned long ino; - if (unlikely(!page)) { - printk(KERN_CRIT "NILFS_PAGE_BUG(NULL)\n"); + if (unlikely(!folio)) { + printk(KERN_CRIT "NILFS_FOLIO_BUG(NULL)\n"); return; } - m = page->mapping; + m = folio->mapping; ino = m ? m->host->i_ino : 0; - printk(KERN_CRIT "NILFS_PAGE_BUG(%p): cnt=%d index#=%llu flags=0x%lx " + printk(KERN_CRIT "NILFS_FOLIO_BUG(%p): cnt=%d index#=%llu flags=0x%lx " "mapping=%p ino=%lu\n", - page, page_ref_count(page), - (unsigned long long)page->index, page->flags, m, ino); + folio, folio_ref_count(folio), + (unsigned long long)folio->index, folio->flags, m, ino); - if (page_has_buffers(page)) { - struct buffer_head *bh, *head; + head = folio_buffers(folio); + if (head) { int i = 0; - bh = head = page_buffers(page); + bh = head; do { printk(KERN_CRIT " BH[%d] %p: cnt=%d block#=%llu state=0x%lx\n",
@@ -257,7 +258,7 @@ int nilfs_copy_dirty_pages(struct address_space *dmap,folio_lock (folio);if (unlikely (!folio_test_dirty (folio))) -NILFS_PAGE_BUG (&folio->page,"inconsistent dirty state" ); +NILFS_FOLIO_BUG (folio,"inconsistent dirty state" ); dfolio =filemap_grab_folio (dmap, folio->index);if (unlikely (IS_ERR (dfolio))) {
@@ -267,7 +268,7 @@ int nilfs_copy_dirty_pages(struct address_space *dmap,break ; }if (unlikely (!folio_buffers (folio))) -NILFS_PAGE_BUG (&folio->page, +NILFS_FOLIO_BUG (folio,"found empty page in dat page cache" );nilfs_copy_page (&dfolio->page, &folio->page,1 );
fs/nilfs2/page.h +3 -3
@@ -37,7 +37,7 @@ struct buffer_head *nilfs_grab_buffer(struct inode *, struct address_space *,void nilfs_forget_buffer (struct buffer_head *);void nilfs_copy_buffer (struct buffer_head *,struct buffer_head *);bool nilfs_folio_buffers_clean (struct folio *); -void nilfs_page_bug (struct page *); +void nilfs_folio_bug (struct folio *);int nilfs_copy_dirty_pages (struct address_space *,struct address_space *);void nilfs_copy_back_pages (struct address_space *,struct address_space *);
@@ -49,8 +49,8 @@ unsigned long nilfs_find_uncommitted_extent(struct inode *inode,sector_t start_blk, sector_t *blkoff); -#define NILFS_PAGE_BUG(page, m, a...) \ - do { nilfs_page_bug(page); BUG(); } while (0) +#define NILFS_FOLIO_BUG(folio, m, a...) \ + do { nilfs_folio_bug(folio); BUG(); } while (0)static inline struct buffer_head *nilfs_page_get_nth_block (struct page *page,unsigned int count)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 913/1424 nilfs2: fix BUG in nilfs_copy_dirty_pages() on dirty state mismatch
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ryusuke Konishi <[email protected]>
[ Upstream commit 66f4ad3ce158902e5f98afea93189972ed8750c2 ]
Syzbot reported a kernel BUG triggered within nilfs_copy_dirty_pages(), which copies dirty DAT file folios/pages to its shadow page cache. The BUG occurs when a retrieved dirty folio/page unexpectedly loses its 'dirty' status.
This issue arises because, since the commit referenced below, the 'dirty' flag of a folio/page can be cleared asynchronously after the filesystem detects metadata corruption and transitions to read-only mode.
Resolve the issue by returning an -EROFS error if the filesystem has transitioned to read-only mode. Also change the behavior to issue a kernel warning only once instead of triggering a kernel BUG when this unexpected 'dirty' state is detected while the filesystem is not in read-only mode.
--- fs/nilfs2/page.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-)
fs/nilfs2/page.c +15 -2
@@ -242,6 +242,7 @@ static void nilfs_copy_page(struct page *dst, struct page *src, int copy_dirty)int nilfs_copy_dirty_pages (struct address_space *dmap,struct address_space *smap) { +struct inode *smap_inode = smap->host;struct folio_batch fbatch;unsigned int i;pgoff_t index =0 ;
@@ -257,8 +258,19 @@ int nilfs_copy_dirty_pages(struct address_space *dmap,struct folio *folio = fbatch.folios[i], *dfolio;folio_lock (folio); -if (unlikely (!folio_test_dirty (folio))) -NILFS_FOLIO_BUG (folio,"inconsistent dirty state" ); +if (unlikely (!folio_test_dirty (folio))) { +if (WARN_ONCE (!sb_rdonly (smap_inode->i_sb), +"inconsistent dirty state\n" )) + goto unlock_folio; + +/* +* If the filesystem has been forced to read-only +* due to metadata corruption. +*/ +folio_unlock (folio); + err = -EROFS ; +break ; + } dfolio =filemap_grab_folio (dmap, folio->index);if (unlikely (IS_ERR (dfolio))) {
@@ -276,6 +288,7 @@ int nilfs_copy_dirty_pages(struct address_space *dmap,folio_unlock (dfolio);folio_put (dfolio); +unlock_folio:folio_unlock (folio); }folio_batch_release (&fbatch);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 914/1424 scsi: smartpqi: Fix AIO retry marker cleared by SCSI core between dispatches.
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Strahan <[email protected]>
[ Upstream commit 225548863f0a2350c6f34231ca56710c3dd1a5d5 ]
On recent Linux kernels the driver can enter a retry loop on the AIO fast path when a request is retried, looping until timeout. A diagnostic path that takes a physical drive offline on AIO-bypass failure is also never entered on affected kernels.
Register a per-command initialization callback with the SCSI core. Its presence causes the core to skip the per-dispatch clear, so the retry marker now survives across the requeue and the AIO-to-RAID fallback proceeds as intended. The driver takes over the marker's lifetime: it is zeroed at tag allocation, preserved across the retry requeue so the error path can act on it, and cleared on terminal completion so the tag starts clean on its next use.
--- drivers/scsi/smartpqi/smartpqi_init.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+)
drivers/scsi/smartpqi/smartpqi_init.c +18 -0
@@ -65,6 +65,12 @@ static struct pqi_cmd_priv *pqi_cmd_priv(struct scsi_cmnd *cmd)return scsi_cmd_priv (cmd); } +static int pqi_init_cmd_priv (struct Scsi_Host *shost,struct scsi_cmnd *cmd) +{ +memset (pqi_cmd_priv (cmd),0 ,sizeof (struct pqi_cmd_priv )); +return 0 ; +} +static void pqi_verify_structures (void );static void pqi_take_ctrl_offline (struct pqi_ctrl_info *ctrl_info,enum pqi_ctrl_shutdown_reason ctrl_shutdown_reason);
@@ -5898,6 +5904,17 @@ void pqi_prep_for_scsi_done(struct scsi_cmnd *scmd)struct pqi_scsi_dev *device;struct completion *wait; +/* +* Clear the AIO-retry marker on final completion so the tag +* starts clean on its next dispatch. On DID_IMM_RETRY leave +* it intact: pqi_aio_io_complete() sets DID_IMM_RETRY and +* bumps the marker to steer the requeue onto the RAID path, +* and pqi_process_raid_io_error() consumes the non-zero +* marker to offline a misbehaving drive. +*/ +if (host_byte (scmd->result) !=DID_IMM_RETRY ) +pqi_cmd_priv (scmd)->this_residual =0 ; +if (!scmd->device) {set_host_byte (scmd,DID_NO_CONNECT );return ;
@@ -7512,6 +7529,7 @@ static const struct scsi_host_template pqi_driver_template = { .sdev_groups = pqi_sdev_groups, .shost_groups = pqi_shost_groups, .cmd_size = sizeof(struct pqi_cmd_priv), + .init_cmd_priv = pqi_init_cmd_priv, };static int pqi_register_scsi (struct pqi_ctrl_info *ctrl_info)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 915/1424 RDMA/mlx5: Fix stack out-of-bounds read in cc_params debugfs
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Leon Romanovsky <[email protected]>
[ Upstream commit 03826bc1fa6c90405bf05831f2b501a8368dcd27 ]
get_param() reads a congestion parameter as a u32 but formats it with the signed "%d" into an 11-byte stack buffer. A value with bit 31 set, such as 0x80000000, renders as "-2147483648\n" whose full length is 12. snprintf() stores only 11 bytes yet returns 12, so simple_read_from_buffer() treats 12 bytes as valid and reads one byte past lbuf[].
Size the buffer for the widest unsigned decimal, format with "%u" to match the u32, and use scnprintf() so the length passed to simple_read_from_buffer() reflects the bytes actually stored.
--- drivers/infiniband/hw/mlx5/cong.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
drivers/infiniband/hw/mlx5/cong.c +2 -4
@@ -399,15 +399,13 @@ static ssize_t get_param(struct file *filp, char __user *buf, size_t count,int offset = param->offset;u32 var =0 ;int ret; -char lbuf[11 ]; +char lbuf[12 ]; ret =mlx5_ib_get_cc_params (param->dev, param->port_num, offset, &var);if (ret)return ret; - ret =snprintf (lbuf,sizeof (lbuf),"%d\n" , var); -if (ret <0 ) -return ret; + ret =scnprintf (lbuf,sizeof (lbuf),"%u\n" , var);return simple_read_from_buffer (buf, count, pos, lbuf, ret); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 916/1424 RDMA/mlx5: Send cong param changes to the resolved port mdev
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Leon Romanovsky <[email protected]>
[ Upstream commit 033a79e308e4fe832b0924347eda8c4364055174 ]
mlx5_ib_set_cc_params() resolves the port-specific mlx5_core_dev via mlx5_ib_get_native_port_mdev() but issued MLX5_CMD_OP_MODIFY_CONG_PARAMS through dev->mdev. On an affiliated secondary RoCE port those pointers refer to different devices, so a write to the secondary port's cc_params debugfs file either altered the master port or failed with a master-side command error, while the read path already used the resolved mdev and returned the unchanged secondary value.
Issue the command to the resolved mdev, the same device whose capabilities were checked when its debugfs directory was created. It is already referenced by the get/put pair, so its lifetime is safe.
--- drivers/infiniband/hw/mlx5/cong.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/infiniband/hw/mlx5/cong.c +1 -1
@@ -361,7 +361,7 @@ static int mlx5_ib_set_cc_params(struct mlx5_ib_dev *dev, u32 port_num,MLX5_SET (field_select_r_roce_rp, field, field_select_r_roce_rp, attr_mask); - err =mlx5_cmd_exec_in (dev->mdev, modify_cong_params, in); + err =mlx5_cmd_exec_in (mdev, modify_cong_params, in);kvfree (in); alloc_err:mlx5_ib_put_native_port_mdev (dev, port_num +1 );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 917/1424 RDMA/cxgb4: free STAG index when TPT entry write fails
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Leon Romanovsky <[email protected]>
[ Upstream commit fdfb5cea4bf070cdb31d997efd87bb684df041fd ]
write_tpt_entry() allocates a new STAG index with c4iw_get_resource() and bumps stats.stag.cur before programming the entry. When write_adapter_mem() fails, it returns the error without releasing the index or reversing the statistic. No MR is inserted into rhp->mrs, so deregistration never reclaims it, leaking the index until device teardown.
Record whether this call allocated the index and, on a failed write, return it to tpt_table and decrement stats.stag.cur. Key the rollback on both the write error and that flag, not the error alone: a non-reset update carries a caller-owned STAG that this call did not allocate and must not free.
--- drivers/infiniband/hw/cxgb4/mem.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/infiniband/hw/cxgb4/mem.c +3 -1
@@ -277,6 +277,7 @@ static int write_tpt_entry(struct c4iw_rdev *rdev, u32 reset_tpt_entry,int err;struct fw_ri_tpte *tpt;u32 stag_idx; +bool stag_idx_allocated = false;static atomic_t key;if (c4iw_fatal_error (rdev))
@@ -299,6 +300,7 @@ static int write_tpt_entry(struct c4iw_rdev *rdev, u32 reset_tpt_entry,return -ENOMEM ; }mutex_lock (&rdev->stats.lock); + stag_idx_allocated = true; rdev->stats.stag.cur +=32 ;if (rdev->stats.stag.cur > rdev->stats.stag.max) rdev->stats.stag.max = rdev->stats.stag.cur;
@@ -333,7 +335,7 @@ static int write_tpt_entry(struct c4iw_rdev *rdev, u32 reset_tpt_entry, (rdev->lldi.vr->stag.start >>5 ), sizeof(*tpt), tpt, skb, wr_waitp); -if (reset_tpt_entry) { +if (reset_tpt_entry || (err && stag_idx_allocated)) {c4iw_put_resource (&rdev->resource.tpt_table, stag_idx);mutex_lock (&rdev->stats.lock); rdev->stats.stag.cur -=32 ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 918/1424 IB/isert: reject PDUs declaring more data than was received
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yehyeong Lee <[email protected]>
[ Upstream commit 957f92ea4022fb6af4618271615a2a21a7b5bef9 ]
isert_recv_done() hands each received PDU to the opcode handlers without ever looking at wc->byte_len, the number of bytes the HCA actually placed in the receive descriptor. The handlers then copy that many bytes - the data-segment length the initiator declared in the BHS (ntoh24(hdr->dlength), via the derived unsol_data_len / imm_data_len) - out of the fixed-size descriptor:
isert_handle_iscsi_dataout():
sg_copy_from_buffer(sg_start, sg_nents, isert_get_data(rx_desc),
unsol_data_len);
isert_handle_scsi_cmd():
sg_copy_from_buffer(cmd->se_cmd.t_data_sg, sg_nents,
isert_get_data(rx_desc), imm_data_len);Because the declared length is never checked against wc->byte_len, an initiator can declare a data segment larger than the bytes it actually sent (and larger than the descriptor) and cause an out-of-bounds read of the receive buffer.
Nothing upstream of isert closes this door:
- __iscsit_check_dataout_hdr() bounds the inbound payload against conn_ops->MaxXmitDataSegmentLength (MXDSL) - a transmit parameter, used here for the inbound check.
- iscsi_set_connection_parameters() sets ops->MaxXmitDataSegmentLength = ops->TargetRecvDataSegmentLength; and TARGETRECVDATASEGMENTLENGTH is absent from the min()-clamp list in iscsi_check_acceptor_state(), so the value the initiator declares is adopted verbatim (type range 512..16777215). The initiator effectively raises its own ceiling.
- isert never clamps the negotiated value to its own fixed receive descriptor (ISER_RX_SIZE, 9216 bytes), so the target core's bound and the descriptor size are unrelated.
The imm_data_len == data_len path is more than an over-read: it aliases the receive descriptor via sg_set_buf() and passes it to the backend as the data source for the SCSI WRITE, so an over-declared length causes heap contents past the descriptor to be written through the backend to the backing store. The backend is the victim of the oversized scatterlist isert hands it, not the cause; no read-back of the written bytes was demonstrated.
Trigger: after login completes (full feature phase), an initiator that has declared a large TargetRecvDataSegmentLength and a FirstBurstLength that permits unsolicited/immediate data sends a PDU whose declared data-segment length exceeds what was received. With KASAN:
BUG: KASAN: slab-out-of-bounds in sg_copy_buffer+0x150/0x1c0 Read of size 4096 at addr ffff888109720800 by task kworker/1:0H/25 Workqueue: ib-comp-wq ib_cq_poll_work Call Trace: sg_copy_buffer+0x150/0x1c0 isert_recv_done+0xba6/0x2390 __ib_process_cq+0xe1/0x390 ib_cq_poll_work+0x46/0x150
isert_recv_done+0xba6 resolves to isert_handle_iscsi_dataout() (ib_isert.c:1160), inlined through isert_rx_opcode().
Validate wc->byte_len against the framing in isert_recv_done() before the PDU reaches any handler, and reinstate the connection if it is short. Because the test compares without subtracting the header length, it also rejects PDUs shorter than the iSER and iSCSI headers, which would otherwise be parsed out of stale descriptor contents. The login handler rejects PDUs shorter than ISER_HEADERS_LEN (commit 29e7b925ae6d ("IB/isert: Reject login PDUs shorter than ISER_HEADERS_LEN")) but does not bound the declared length either; that is fixed in the next patch. The data handlers had no length check at all.
isert reads the data segment from a fixed offset: isert_get_data() returns the iSER header plus ISER_HEADERS_LEN and makes no adjustment for an AHS. The bytes the handlers touch are therefore exactly [ISER_HEADERS_LEN, ISER_HEADERS_LEN + dlength), and comparing that sum against wc->byte_len bounds precisely the region that is read. An AHS term would only make the test stricter without bounding anything further, and cannot cause a false reject: a PDU carrying an AHS is longer, not shorter.
This is a memory-safety fix that verifies the bytes that were actually received; it does not touch RFC 7145 length negotiation and is not the MaxXmitDataSegmentLength negotiation redesign raised in the 2017 "[Query]
iSER-Target: QP errors observed on increasing MaxXmitDataSegmentLength" discussion. That redesign is explicitly out of scope here.
The patched kernel rejects the malformed DataOut PDU and both immediate-data variants with "PDU declares ... bytes were received" and continues to pass normal traffic with no regression.
Reproduced with soft-RoCE (rdma_rxe) and a raw rdma_cm/ibv initiator; no kernel-side test hooks were needed.
--- drivers/infiniband/ulp/isert/ib_isert.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+)
drivers/infiniband/ulp/isert/ib_isert.c +15 -0
@@ -1338,6 +1338,21 @@ isert_recv_done(struct ib_cq *cq, struct ib_wc *wc)ib_dma_sync_single_for_cpu (ib_dev, rx_desc->dma_addr,ISER_RX_SIZE ,DMA_FROM_DEVICE ); +/* +* The data segment length declared in the BHS is attacker controlled +* and is used further down to read that many bytes out of the fixed +* size receive descriptor, so it has to be checked against the number +* of bytes that were actually received. Comparing without subtracting +* also rejects PDUs shorter than the iSER and iSCSI headers, which +* would otherwise be parsed out of stale descriptor contents. +*/ +if (unlikely (wc->byte_len <ISER_HEADERS_LEN +ntoh24 (hdr->dlength))) { +isert_err ("PDU declares %u data bytes but only %u bytes were received\n" , +ntoh24 (hdr->dlength), wc->byte_len); +iscsit_cause_connection_reinstatement (isert_conn->conn,0 ); +return ; + } +isert_dbg ("DMA: 0x%llx, iSCSI opcode: 0x%02x, ITT: 0x%08x, flags: 0x%02x dlen: %d\n" , rx_desc->dma_addr, hdr->opcode, hdr->itt, hdr->flags, (int )(wc->byte_len -ISER_HEADERS_LEN ));
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 919/1424 IB/isert: reject login PDUs declaring more data than was received
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yehyeong Lee <[email protected]>
[ Upstream commit 2488b5b4827e5415768afc8daf097e8eb83c98df ]
isert_login_recv_done() records how many bytes the HCA actually placed in the login buffer, but nothing compares that against the length the login PDU's BHS declares. isert_rx_login_req() copies min(login_req_len, MAX_KEY_VALUE_PAIRS) bytes into login->req_buf, and the login code then reads the declared length back out of that buffer - for the first PDU in iscsi_target_locate_portal(),
payload_length = ntoh24(login_req->dlength); tmpbuf = kmemdup_nul(login->req_buf, payload_length, GFP_KERNEL);
and for the ones after it in iscsi_decode_text_input(), reached from iscsi_target_do_login().
login->req_buf is a fixed MAX_KEY_VALUE_PAIRS (8192) byte allocation, so an initiator that declares more than it sends reads off the end of it, before authentication and with the length under its control:
BUG: KASAN: slab-out-of-bounds in kmemdup_nul+0x43/0x80 Read of size 8193 at addr ffff8881056a8000 by task iscsi_np/167 __asan_memcpy+0x23/0x60 kmemdup_nul+0x43/0x80 iscsi_target_locate_portal+0x48d/0x1180 iscsi_target_login_thread+0x19a9/0x3350 Allocated by task 167: __kmalloc_cache_noprof+0x158/0x370 iscsi_target_login_thread+0x971/0x3350 which belongs to the cache kmalloc-8k of size 8192 allocated 8192-byte region
Falsifying the second login PDU instead reaches the other reader, on the same buffer:
BUG: KASAN: slab-out-of-bounds in kmemdup_nul+0x43/0x80 Read of size 8193 at addr ffff888104d10000 by task kworker/1:1/50 Workqueue: isert_login_wq iscsi_target_do_login_rx __asan_memcpy+0x23/0x60 kmemdup_nul+0x43/0x80 iscsi_decode_text_input+0xc6/0x11c0 iscsi_target_do_login+0x261/0x1470 iscsi_target_do_login_rx+0x51d/0x7d0
iscsit over TCP is not exposed: iscsit_get_login_rx() validates the declared length with iscsi_target_check_login_request() and then reads exactly that many bytes off the socket, so the declared length governs how much arrives rather than how much is copied out of an already-filled buffer. isert does not call iscsi_target_check_login_request() at all.
Reject a login PDU whose declared DataSegmentLength exceeds what was received, in both paths that reach isert_rx_login_req():isert_get_login_rx() for the first login PDU and isert_login_recv_done() for the ones after it. dlength <= login_req_len is allowed because the received count can include up to three bytes of iSCSI padding.
Once the check is in place the copy out can no longer exceed the copy in:
the posted login SGE is ISER_RX_PAYLOAD_SIZE, so login_req_len cannot exceed MAX_KEY_VALUE_PAIRS and the min() in isert_rx_login_req() is login_req_len.
Like the existing short-PDU check added by 29e7b925ae6d, the reject in isert_login_recv_done() returns without completing login_req_comp, so a malformed subsequent PDU leaves the login to be torn down by the login timer rather than failing immediately. The first-PDU path returns an error and fails straight away.
Reproduced on 7.2.0-rc4 with soft-RoCE (rdma_rxe) under KASAN, using an initiator that sends the real key=value payload while declaring 8193 in the BHS, on the first login PDU and on the second in separate runs. The reported read size tracks the declared value exactly; 16384 and 61440 behave the same. Unpatched 3 of 3 runs report on each of the two paths, patched 0 of 3 on both, run alternately in a single session, and a normal login still completes on the patched build.
--- drivers/infiniband/ulp/isert/ib_isert.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-)
drivers/infiniband/ulp/isert/ib_isert.c +24 -1
@@ -976,6 +976,21 @@ isert_put_login_tx(struct iscsit_conn *conn, struct iscsi_login *login,return 0 ; } +static int +isert_check_login_req (struct isert_conn *isert_conn) +{ +struct iscsi_hdr *hdr =isert_get_iscsi_hdr (isert_conn->login_desc); +u32 dlength =ntoh24 (hdr->dlength); + +if (unlikely (dlength > (u32 )isert_conn->login_req_len)) { +isert_dbg ("login PDU declares %u data bytes but only %d were received\n" , + dlength, isert_conn->login_req_len); +return -EINVAL ; + } + +return 0 ; +} +static void isert_rx_login_req (struct isert_conn *isert_conn) {
@@ -1414,8 +1429,12 @@ isert_login_recv_done(struct ib_cq *cq, struct ib_wc *wc)if (isert_conn->conn) {struct iscsi_login *login = isert_conn->conn->conn_login; -if (login && !login->first_request) +if (login && !login->first_request) { +if (isert_check_login_req (isert_conn)) +return ; +isert_rx_login_req (isert_conn); + } }mutex_lock (&isert_conn->mutex);
@@ -2380,6 +2399,10 @@ isert_get_login_rx(struct iscsit_conn *conn, struct iscsi_login *login)if (!login->first_request)return 0 ; + ret =isert_check_login_req (isert_conn); +if (ret) +return ret; +isert_rx_login_req (isert_conn);isert_info ("before login_comp conn: %p\n" , conn);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 920/1424 nvme-fc: unmap cmd_iu DMA on rsp_iu mapping failure in init_request
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guixin Liu <[email protected]>
[ Upstream commit f49d0c3a8d56a7cda1628ae17341a4a42063563c ]
__nvme_fc_init_request() maps cmd_iu and then rsp_iu for DMA. If the rsp_iu mapping fails, the original code only recorded the error and fell
through: it left the already-mapped cmd_iu unmapped and still marked the op as FCPOP_STATE_IDLE before returning. Since blk-mq does not call .exit_request() when .init_request() fails, the cmd_iu mapping is leaked for every op whose rsp_iu mapping fails.
Jump to an error path on rsp_iu mapping failure that unmaps cmd_iu and returns the error without marking the op idle, so it stays in the FCPOP_STATE_UNINIT state set by the initial memset().
--- drivers/nvme/host/fc.c | 6 ++++++ 1 file changed, 6 insertions(+)
drivers/nvme/host/fc.c +6 -0
@@ -2092,9 +2092,15 @@ __nvme_fc_init_request(struct nvme_fc_ctrl *ctrl,dev_err (ctrl->dev,"FCP Op failed - rspiu dma mapping failed.\n" ); ret = -EFAULT ; + goto out_unmap; }atomic_set (&op->state,FCPOP_STATE_IDLE ); +return 0 ; + +out_unmap: +fc_dma_unmap_single (ctrl->lport->dev, op->fcp_req.cmddma, +sizeof (op->cmd_iu),DMA_TO_DEVICE ); out_on_error:return ret; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 921/1424 spi: davinci: Use helper function devm_clk_get_enabled()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Li Zetao <[email protected]>
[ Upstream commit 9dc2aa96a3533215fbed9cf1297f7aa70dae840b ]
Since commit 7ef9651e9792 ("clk: Provide new devm_clk helpers for prepared and enabled clocks"), devm_clk_get() and clk_prepare_enable() can now be replaced by devm_clk_get_enabled() when driver enables (and possibly prepares) the clocks for the whole lifetime of the device. Moreover, it is no longer necessary to unprepare and disable the clocks explicitly.
Stable-dep-of: ea408a05dc8f ("spi: davinci: switch to managed controller allocation")
--- drivers/spi/spi-davinci.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-)
drivers/spi/spi-davinci.c +2 -9
@@ -915,14 +915,11 @@ static int davinci_spi_probe(struct platform_device *pdev) dspi->bitbang.master = host; - dspi->clk =devm_clk_get (&pdev->dev,NULL ); + dspi->clk =devm_clk_get_enabled (&pdev->dev,NULL );if (IS_ERR (dspi->clk)) { ret = -ENODEV ; goto free_host; } - ret =clk_prepare_enable (dspi->clk); -if (ret) - goto free_host; host->use_gpio_descriptors = true; host->dev.of_node = pdev->dev.of_node;
@@ -947,7 +944,7 @@ static int davinci_spi_probe(struct platform_device *pdev) ret =davinci_spi_request_dma (dspi);if (ret == -EPROBE_DEFER ) { - goto free_clk; + goto free_host; }else if (ret) {dev_info (&pdev->dev,"DMA is not supported (%d)\n" , ret); dspi->dma_rx =NULL ;
@@ -991,8 +988,6 @@ static int davinci_spi_probe(struct platform_device *pdev)dma_release_channel (dspi->dma_rx);dma_release_channel (dspi->dma_tx); } -free_clk: -clk_disable_unprepare (dspi->clk); free_host:spi_controller_put (host); err:
@@ -1018,8 +1013,6 @@ static void davinci_spi_remove(struct platform_device *pdev)spi_bitbang_stop (&dspi->bitbang); -clk_disable_unprepare (dspi->clk); -if (dspi->dma_rx) {dma_release_channel (dspi->dma_rx);dma_release_channel (dspi->dma_tx);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 922/1424 spi: davinci: Unset POWERDOWN bit when releasing resources
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bastien Curutchet <[email protected]>
[ Upstream commit 1762dc01fc78ef5f19693e9317eae7491c6c7e1b ]
On the OMAPL138, the SPI reference clock is provided by the Power and Sleep Controller (PSC). The PSC's datasheet says that 'some peripherals have special programming requirements and additional recommended steps you must take before you can invoke the PSC module state transition'. I didn't find more details in documentation but it appears that PSC needs the SPI to clear the POWERDOWN bit before disabling the clock. Indeed, when this bit is set, the PSC gets stuck in transitions from enable to disable state.
Clear the POWERDOWN bit when releasing driver's resources
Stable-dep-of: ea408a05dc8f ("spi: davinci: switch to managed controller allocation")
--- drivers/spi/spi-davinci.c | 6 ++++++ 1 file changed, 6 insertions(+)
drivers/spi/spi-davinci.c +6 -0
@@ -984,6 +984,9 @@ static int davinci_spi_probe(struct platform_device *pdev)return ret; free_dma: +/* This bit needs to be cleared to disable dpsi->clk */ +clear_io_bits (dspi->base +SPIGCR1 ,SPIGCR1_POWERDOWN_MASK ); +if (dspi->dma_rx) {dma_release_channel (dspi->dma_rx);dma_release_channel (dspi->dma_tx);
@@ -1013,6 +1016,9 @@ static void davinci_spi_remove(struct platform_device *pdev)spi_bitbang_stop (&dspi->bitbang); +/* This bit needs to be cleared to disable dpsi->clk */ +clear_io_bits (dspi->base +SPIGCR1 ,SPIGCR1_POWERDOWN_MASK ); +if (dspi->dma_rx) {dma_release_channel (dspi->dma_rx);dma_release_channel (dspi->dma_tx);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 923/1424 spi: davinci: switch to managed controller allocation
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Fan Wu <[email protected]>
[ Upstream commit ea408a05dc8f18b4a184b88d6e19d2fd1acc1527 ]
The controller is allocated with the non-managed spi_alloc_host() while the interrupt is registered with devm_request_threaded_irq(). During removal, spi_bitbang_stop() only unregisters the controller; the subsequent spi_controller_put() then frees the controller together with its embedded davinci_spi devdata, which is the IRQ handler's dev_id. The devm_request_threaded_irq() release action (free_irq()), which drains the handler, does not run until after .remove() returns. A late or latched interrupt can therefore reach davinci_spi_irq() and dereference already-freed memory.
Switch to devm_spi_alloc_host() so that the devres LIFO order releases the controller only after free_irq() has drained the handler, and drop the now-redundant spi_controller_put() from .remove(). The probe error path is simplified to direct returns.
The clock is acquired with devm_clk_get_enabled(), which is registered after the IRQ and thus released before it by the devres LIFO order. Drain the interrupt explicitly with devm_free_irq() before disabling the controller so that a late interrupt cannot access the registers of a clock-gated controller.
This issue was found by an in-house static analysis tool.
--- drivers/spi/spi-davinci.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-)
drivers/spi/spi-davinci.c +3 -4
@@ -862,7 +862,7 @@ static int davinci_spi_probe(struct platform_device *pdev)int ret =0 ;u32 spipc0; - host =spi_alloc_host (&pdev->dev,sizeof (struct davinci_spi )); + host =devm_spi_alloc_host (&pdev->dev,sizeof (struct davinci_spi ));if (host ==NULL ) { ret = -ENOMEM ; goto err;
@@ -992,7 +992,6 @@ static int davinci_spi_probe(struct platform_device *pdev)dma_release_channel (dspi->dma_tx); } free_host: -spi_controller_put (host); err:return ret; }
@@ -1016,6 +1015,8 @@ static void davinci_spi_remove(struct platform_device *pdev)spi_bitbang_stop (&dspi->bitbang); +devm_free_irq (&pdev->dev, dspi->irq, dspi); +/* This bit needs to be cleared to disable dpsi->clk */ clear_io_bits (dspi->base +SPIGCR1 ,SPIGCR1_POWERDOWN_MASK );
@@ -1023,8 +1024,6 @@ static void davinci_spi_remove(struct platform_device *pdev)dma_release_channel (dspi->dma_rx);dma_release_channel (dspi->dma_tx); } - -spi_controller_put (host); }static struct platform_driver davinci_spi_driver = {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 924/1424 wifi: ath11k: qmi: refactor ath11k_qmi_m3_load()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kalle Valo <[email protected]>
[ Upstream commit b49381d3de3af1b84b4b1f08eda301b8befb4b05 ]
Simple refactoring to make it easier to add firmware-2.bin support in the following patch.
Earlier ath11k_qmi_m3_load() supported changing m3.bin contents while ath11k is running. But that's not going to actually work, m3.bin is supposed to be the same during the lifetime of ath11k, for example we don't support changing the firmware capabilities on the fly. Due to this ath11k requests m3.bin firmware file first and only then checks m3_mem->vaddr, so we are basically requesting the firmware file even if it's not needed. Reverse the code so that m3_mem buffer is checked first, and only if it doesn't exist, then m3.bin is requested from user space.
Checking for m3_mem->size is redundant when m3_mem->vaddr is NULL, we would not be able to use the buffer in that case. So remove the check for size.
Simplify the exit handling and use 'goto out'.
Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.9
Stable-dep-of: 208d7fdb8597 ("wifi: ath11k: fix overreads in ath11k_wmi_process_csa_switch_count_event()")
--- drivers/net/wireless/ath/ath11k/qmi.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-)
drivers/net/wireless/ath/ath11k/qmi.c +11 -7
@@ -2518,6 +2518,10 @@ static int ath11k_qmi_m3_load(struct ath11k_base *ab)char path[100 ];int ret; +if (m3_mem->vaddr) +/* m3 firmware buffer is already available in the DMA buffer */ +return 0 ; + fw =ath11k_core_firmware_request (ab,ATH11K_M3_FILE );if (IS_ERR (fw)) { ret =PTR_ERR (fw);
@@ -2527,25 +2531,25 @@ static int ath11k_qmi_m3_load(struct ath11k_base *ab)return ret; } -if (m3_mem->vaddr || m3_mem->size) - goto skip_m3_alloc; - m3_mem->vaddr =dma_alloc_coherent (ab->dev, fw->size, &m3_mem->paddr,GFP_KERNEL );if (!m3_mem->vaddr) {ath11k_err (ab,"failed to allocate memory for M3 with size %zu\n" , fw->size); -release_firmware (fw); -return -ENOMEM ; + ret = -ENOMEM ; + goto out; } -skip_m3_alloc:memcpy (m3_mem->vaddr, fw->data, fw->size); m3_mem->size = fw->size; + + ret =0 ; + +out:release_firmware (fw); -return 0 ; +return ret; }static void ath11k_qmi_m3_free (struct ath11k_base *ab)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 925/1424 wifi: ath11k: add firmware-2.bin support
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Anilkumar Kolli <[email protected]>
[ Upstream commit 7db88b962f06a52af5e9a32971012e8f3427cec0 ]
Firmware IE containers can dynamically provide various information what firmware supports. Also it can embed more than one image so updating firmware is easy, user just needs to update one file in /lib/firmware/.
The firmware API 2 or higher will use the IE container format, the current API 1 will not use the new format but it still is supported for some time. Firmware API 2 files are named as firmware-2.bin (which contains both amss.bin and m3.bin images) and API 1 files are amss.bin and m3.bin.
Currently ath11k PCI driver provides firmware binary (amss.bin) path to MHI driver, MHI driver reads firmware from filesystem and boots it. Add provision to read firmware files from ath11k driver and provide the amss.bin firmware data and size to MHI using a pointer.
Currently enum ath11k_fw_features is empty, the patches adding features will add the flags.
With AHB devices there's no amss.bin or m3.bin, so no changes in how AHB firmware files are used. But AHB devices can use future additions to the meta data, for example in enum ath11k_fw_features.
Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.9
Stable-dep-of: 208d7fdb8597 ("wifi: ath11k: fix overreads in ath11k_wmi_process_csa_switch_count_event()")
--- drivers/net/wireless/ath/ath11k/Makefile | 3 +- drivers/net/wireless/ath/ath11k/core.c | 8 ++ drivers/net/wireless/ath/ath11k/core.h | 15 ++ drivers/net/wireless/ath/ath11k/fw.c | 168 +++++++++++++++++++++++ drivers/net/wireless/ath/ath11k/fw.h | 27 ++++ drivers/net/wireless/ath/ath11k/mhi.c | 18 ++- drivers/net/wireless/ath/ath11k/qmi.c | 36 +++-- 7 files changed, 258 insertions(+), 17 deletions(-) create mode 100644 drivers/net/wireless/ath/ath11k/fw.c create mode 100644 drivers/net/wireless/ath/ath11k/fw.h
drivers/net/wireless/ath/ath11k/Makefile +2 -1
@@ -17,7 +17,8 @@ ath11k-y += core.o \ peer.o \ dbring.o \ hw.o \ - pcic.o + pcic.o \ + fw.o ath11k-$(CONFIG_ATH11K_DEBUGFS) += debugfs.o debugfs_htt_stats.o debugfs_sta.o ath11k-$(CONFIG_NL80211_TESTMODE) += testmode.o
drivers/net/wireless/ath/ath11k/core.c +8 -0
@@ -16,6 +16,7 @@#include "debug.h" #include "hif.h" #include "wow.h" +#include "fw.h" unsigned int ath11k_debug_mask;EXPORT_SYMBOL (ath11k_debug_mask);
@@ -2124,6 +2125,12 @@ int ath11k_core_pre_init(struct ath11k_base *ab)return ret; } + ret =ath11k_fw_pre_init (ab); +if (ret) { +ath11k_err (ab,"failed to pre init firmware: %d" , ret); +return ret; + } +return 0 ; }EXPORT_SYMBOL (ath11k_core_pre_init);
@@ -2163,6 +2170,7 @@ void ath11k_core_deinit(struct ath11k_base *ab)ath11k_hif_power_down (ab);ath11k_mac_destroy (ab);ath11k_core_soc_destroy (ab); +ath11k_fw_destroy (ab); }EXPORT_SYMBOL (ath11k_core_deinit);
drivers/net/wireless/ath/ath11k/core.h +15 -0
@@ -15,6 +15,8 @@#include <linux/ctype.h> #include <linux/rhashtable.h> #include <linux/average.h> +#include <linux/firmware.h> +#include "qmi.h" #include "htc.h" #include "wmi.h"
@@ -29,6 +31,7 @@#include "dbring.h" #include "spectral.h" #include "wow.h" +#include "fw.h" #define SM (_v, _f) (((_v) << _f##_LSB) & _f##_MASK)
@@ -993,6 +996,18 @@ struct ath11k_base {const struct ath11k_pci_ops *ops; } pci; +struct { +u32 api_version; + +const struct firmware *fw; +const u8 *amss_data; +size_t amss_len; +const u8 *m3_data; +size_t m3_len; + + DECLARE_BITMAP(fw_features, ATH11K_FW_FEATURE_COUNT); + } fw; + #ifdef CONFIG_NL80211_TESTMODE struct { u32 data_pos;
drivers/net/wireless/ath/ath11k/fw.c new file +168 -0
168 lines not on this page · raw message
drivers/net/wireless/ath/ath11k/fw.h new file +27 -0
@@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: BSD-3-Clause-Clear */ +/* +* Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved. +*/ + +#ifndef ATH11K_FW_H +#define ATH11K_FW_H + +#define ATH11K_FW_API2_FILE "firmware-2.bin" +#define ATH11K_FIRMWARE_MAGIC "QCOM-ATH11K-FW" + +enum ath11k_fw_ie_type { +ATH11K_FW_IE_TIMESTAMP =0 , +ATH11K_FW_IE_FEATURES =1 , +ATH11K_FW_IE_AMSS_IMAGE =2 , +ATH11K_FW_IE_M3_IMAGE =3 , +}; + +enum ath11k_fw_features { +/* keep last */ +ATH11K_FW_FEATURE_COUNT , +}; + +int ath11k_fw_pre_init (struct ath11k_base *ab); +void ath11k_fw_destroy (struct ath11k_base *ab); + +#endif /* ATH11K_FW_H */
drivers/net/wireless/ath/ath11k/mhi.c +13 -5
@@ -6,6 +6,7 @@#include <linux/msi.h> #include <linux/pci.h> +#include <linux/firmware.h> #include <linux/of.h> #include <linux/of_address.h> #include <linux/ioport.h>
@@ -389,16 +390,23 @@ int ath11k_mhi_register(struct ath11k_pci *ab_pci)if (!mhi_ctrl)return -ENOMEM ; -ath11k_core_create_firmware_path (ab,ATH11K_AMSS_FILE , - ab_pci->amss_path, -sizeof (ab_pci->amss_path)); - ab_pci->mhi_ctrl = mhi_ctrl; mhi_ctrl->cntrl_dev = ab->dev; - mhi_ctrl->fw_image = ab_pci->amss_path; mhi_ctrl->regs = ab->mem; mhi_ctrl->reg_len = ab->mem_len; +if (ab->fw.amss_data && ab->fw.amss_len >0 ) { +/* use MHI firmware file from firmware-N.bin */ + mhi_ctrl->fw_data = ab->fw.amss_data; + mhi_ctrl->fw_sz = ab->fw.amss_len; + }else { +/* use the old separate mhi.bin MHI firmware file */ +ath11k_core_create_firmware_path (ab,ATH11K_AMSS_FILE , + ab_pci->amss_path, +sizeof (ab_pci->amss_path)); + mhi_ctrl->fw_image = ab_pci->amss_path; + } + ret =ath11k_mhi_get_msi (ab_pci);if (ret) {ath11k_err (ab,"failed to get msi for mhi\n" );
drivers/net/wireless/ath/ath11k/qmi.c +25 -11
@@ -2514,25 +2514,39 @@ static int ath11k_qmi_load_bdf_qmi(struct ath11k_base *ab,static int ath11k_qmi_m3_load (struct ath11k_base *ab) {struct m3_mem_region *m3_mem = &ab->qmi.m3_mem; -const struct firmware *fw; +const struct firmware *fw =NULL ; +const void *m3_data;char path[100 ]; +size_t m3_len;int ret;if (m3_mem->vaddr)/* m3 firmware buffer is already available in the DMA buffer */ return 0 ; - fw =ath11k_core_firmware_request (ab,ATH11K_M3_FILE ); -if (IS_ERR (fw)) { - ret =PTR_ERR (fw); -ath11k_core_create_firmware_path (ab,ATH11K_M3_FILE , - path,sizeof (path)); -ath11k_err (ab,"failed to load %s: %d\n" , path, ret); -return ret; +if (ab->fw.m3_data && ab->fw.m3_len >0 ) { +/* firmware-N.bin had a m3 firmware file so use that */ + m3_data = ab->fw.m3_data; + m3_len = ab->fw.m3_len; + }else { +/* No m3 file in firmware-N.bin so try to request old +* separate m3.bin. +*/ + fw =ath11k_core_firmware_request (ab,ATH11K_M3_FILE ); +if (IS_ERR (fw)) { + ret =PTR_ERR (fw); +ath11k_core_create_firmware_path (ab,ATH11K_M3_FILE , + path,sizeof (path)); +ath11k_err (ab,"failed to load %s: %d\n" , path, ret); +return ret; + } + + m3_data = fw->data; + m3_len = fw->size; } m3_mem->vaddr =dma_alloc_coherent (ab->dev, - fw->size, &m3_mem->paddr, + m3_len, &m3_mem->paddr,GFP_KERNEL );if (!m3_mem->vaddr) { ath11k_err(ab, "failed to allocate memory for M3 with size %zu\n",
@@ -2541,8 +2555,8 @@ static int ath11k_qmi_m3_load(struct ath11k_base *ab) goto out; } -memcpy (m3_mem->vaddr, fw->data, fw->size); - m3_mem->size = fw->size; +memcpy (m3_mem->vaddr, m3_data, m3_len); + m3_mem->size = m3_len; ret =0 ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 926/1424 wifi: ath11k: refactor ath11k_wmi_tlv_parse_alloc()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Antipov <[email protected]>
[ Upstream commit f5e6c0c4b0877e0ec0221df6c0041c0f39b6ce0f ]
Since 'ath11k_wmi_tlv_parse_alloc()' always operates on 'skb->data, skb->len' tuple, it may be simplified to pass the only 'skb' argument instead (which also implies refactoring of 'ath11k_pull_bcn_tx_status_ev()' and 'ath11k_pull_chan_info_ev()' in the same way). Compile tested only.
Stable-dep-of: 208d7fdb8597 ("wifi: ath11k: fix overreads in ath11k_wmi_process_csa_switch_count_event()")
--- drivers/net/wireless/ath/ath11k/testmode.c | 2 +- drivers/net/wireless/ath/ath11k/wmi.c | 73 +++++++++++----------- drivers/net/wireless/ath/ath11k/wmi.h | 4 +- 3 files changed, 39 insertions(+), 40 deletions(-)
drivers/net/wireless/ath/ath11k/testmode.c +1 -1
@@ -198,7 +198,7 @@ static void ath11k_tm_wmi_event_segmented(struct ath11k_base *ab, u32 cmd_id,u16 length;int ret; - tb =ath11k_wmi_tlv_parse_alloc (ab, skb->data, skb->len,GFP_ATOMIC ); + tb =ath11k_wmi_tlv_parse_alloc (ab, skb,GFP_ATOMIC );if (IS_ERR (tb)) { ret =PTR_ERR (tb);ath11k_warn (ab,"failed to parse ftm event tlv: %d\n" , ret);
drivers/net/wireless/ath/ath11k/wmi.c +36 -37
263 lines not on this page · raw message
drivers/net/wireless/ath/ath11k/wmi.h +2 -2
@@ -6320,8 +6320,8 @@ enum wmi_sta_keepalive_method {#define WMI_STA_KEEPALIVE_INTERVAL_DEFAULT 30#define WMI_STA_KEEPALIVE_INTERVAL_DISABLE 0 -const void **ath11k_wmi_tlv_parse_alloc (struct ath11k_base *ab,const void *ptr, -size_t len,gfp_t gfp); +const void **ath11k_wmi_tlv_parse_alloc (struct ath11k_base *ab, +struct sk_buff *skb,gfp_t gfp);int ath11k_wmi_cmd_send (struct ath11k_pdev_wmi *wmi,struct sk_buff *skb,u32 cmd_id);struct sk_buff *ath11k_wmi_alloc_skb (struct ath11k_wmi_base *wmi_sc,u32 len);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 927/1424 wifi: ath11k: implement handling of P2P NoA event
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kang Yang <[email protected]>
[ Upstream commit 2408379f15a1039eb47da01c6d197112332fc4a7 ]
The NoA(Notice of Absence) attribute is used by the P2P Group Owner to signal its absence due to power save timing, concurrent operation, or off-channel scanning. It is also used in the P2P Presence Request-Response mechanism.
The NoA attribute shall be present in the P2P IE in the beacon frames transmitted by a P2P Group Owner when a NoA schedule is being advertised, or when the CTWindow is non-zero.
So add support to update P2P information after P2P GO is up through event WMI_P2P_NOA_EVENTID, and always put it in probe resp.
Create p2p.c and p2p.h for P2P related functions and definitions.
Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.37
Tested-on: QCA2066 hw2.1 PCI WLAN.HSP.1.1-03926.13-QCAHSPSWPL_V2_SILICONZ_CE-2.52297.2
Stable-dep-of: 208d7fdb8597 ("wifi: ath11k: fix overreads in ath11k_wmi_process_csa_switch_count_event()")
--- drivers/net/wireless/ath/ath11k/Makefile | 3 +- drivers/net/wireless/ath/ath11k/p2p.c | 149 +++++++++++++++++++++++ drivers/net/wireless/ath/ath11k/p2p.h | 22 ++++ drivers/net/wireless/ath/ath11k/wmi.c | 68 ++++++++++- drivers/net/wireless/ath/ath11k/wmi.h | 31 +++++ 5 files changed, 271 insertions(+), 2 deletions(-) create mode 100644 drivers/net/wireless/ath/ath11k/p2p.c create mode 100644 drivers/net/wireless/ath/ath11k/p2p.h
drivers/net/wireless/ath/ath11k/Makefile +2 -1
@@ -18,7 +18,8 @@ ath11k-y += core.o \ dbring.o \ hw.o \ pcic.o \ - fw.o + fw.o \ + p2p.o ath11k-$(CONFIG_ATH11K_DEBUGFS) += debugfs.o debugfs_htt_stats.o debugfs_sta.o ath11k-$(CONFIG_NL80211_TESTMODE) += testmode.o
drivers/net/wireless/ath/ath11k/p2p.c new file +149 -0
149 lines not on this page · raw message
drivers/net/wireless/ath/ath11k/p2p.h new file +22 -0
@@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: BSD-3-Clause-Clear */ +/* +* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. +*/ + +#ifndef ATH11K_P2P_H +#define ATH11K_P2P_H + +#include "wmi.h" + +struct ath11k_wmi_p2p_noa_info ; + +struct ath11k_p2p_noa_arg { +u32 vdev_id; +const struct ath11k_wmi_p2p_noa_info *noa; +}; + +void ath11k_p2p_noa_update (struct ath11k_vif *arvif, +const struct ath11k_wmi_p2p_noa_info *noa); +void ath11k_p2p_noa_update_by_vdev_id (struct ath11k *ar,u32 vdev_id, +const struct ath11k_wmi_p2p_noa_info *noa); +#endif
drivers/net/wireless/ath/ath11k/wmi.c +67 -1
98 lines not on this page · raw message
drivers/net/wireless/ath/ath11k/wmi.h +31 -0
@@ -3584,6 +3584,37 @@ struct wmi_ftm_event_msg {u8 data[]; } __packed; +#define WMI_P2P_MAX_NOA_DESCRIPTORS 4 + +struct wmi_p2p_noa_event { +u32 vdev_id; +} __packed; + +struct ath11k_wmi_p2p_noa_descriptor { +u32 type_count;/* 255: continuous schedule, 0: reserved */ +u32 duration;/* Absent period duration in micro seconds */ +u32 interval;/* Absent period interval in micro seconds */ +u32 start_time;/* 32 bit tsf time when in starts */ +} __packed; + +#define WMI_P2P_NOA_INFO_CHANGED_FLAG BIT(0) +#define WMI_P2P_NOA_INFO_INDEX GENMASK(15, 8) +#define WMI_P2P_NOA_INFO_OPP_PS BIT(16) +#define WMI_P2P_NOA_INFO_CTWIN_TU GENMASK(23, 17) +#define WMI_P2P_NOA_INFO_DESC_NUM GENMASK(31, 24) + +struct ath11k_wmi_p2p_noa_info { +/* Bit 0 - Flag to indicate an update in NOA schedule +* Bits 7-1 - Reserved +* Bits 15-8 - Index (identifies the instance of NOA sub element) +* Bit 16 - Opp PS state of the AP +* Bits 23-17 - Ctwindow in TUs +* Bits 31-24 - Number of NOA descriptors +*/ +u32 noa_attr; +struct ath11k_wmi_p2p_noa_descriptor descriptors[WMI_P2P_MAX_NOA_DESCRIPTORS ]; +} __packed; +#define WMI_BEACON_TX_BUFFER_SIZE 512#define WMI_EMA_TMPL_IDX_SHIFT 8
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 928/1424 wifi: ath11k: fix overreads in ath11k_wmi_process_csa_switch_count_event()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jeff Johnson <[email protected]>
[ Upstream commit 208d7fdb85976a737a715b81d54efaff6703880c ]
There is no policy entry for WMI_TAG_PDEV_CSA_SWITCH_COUNT_STATUS_EVENT, so the parse infrastructure does not enforce a minimum length for the event struct. Additionally, the num_vdevs field is taken directly from firmware and used as a loop bound over the vdev_ids array without checking that it fits within the TLV payload. Either condition can cause an out-of-bounds read.
Add a TLV policy entry for WMI_TAG_PDEV_CSA_SWITCH_COUNT_STATUS_EVENT so the parse infrastructure enforces a minimum length for the fixed-size event struct. Add a helper ath11k_wmi_tlv_data_len() to recover the payload length of a parsed TLV from the header preceding its data pointer. Use it in ath11k_wmi_process_csa_switch_count_event() to bound num_vdevs before the loop.
Compile tested only.
--- drivers/net/wireless/ath/ath11k/wmi.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-)
drivers/net/wireless/ath/ath11k/wmi.c +19 -2
@@ -159,6 +159,8 @@ static const struct wmi_tlv_policy wmi_tlv_policies[] = { .min_len = sizeof(struct ath11k_wmi_p2p_noa_info) }, [WMI_TAG_P2P_NOA_EVENT] = { .min_len = sizeof(struct wmi_p2p_noa_event) }, + [WMI_TAG_PDEV_CSA_SWITCH_COUNT_STATUS_EVENT] = { + .min_len = sizeof(struct wmi_pdev_csa_switch_ev) }, };#define PRIMAP (_hw_mode_) \
@@ -262,6 +264,13 @@ const void **ath11k_wmi_tlv_parse_alloc(struct ath11k_base *ab,return tb; } +static u32 ath11k_wmi_tlv_data_len (const void *data) +{ +const struct wmi_tlv *tlv = (const struct wmi_tlv *)data -1 ; + +return FIELD_GET (WMI_TLV_LEN , tlv->header); +} +static int ath11k_wmi_cmd_send_nowait (struct ath11k_pdev_wmi *wmi,struct sk_buff *skb,u32 cmd_id) {
@@ -8260,15 +8269,23 @@ ath11k_wmi_process_csa_switch_count_event(struct ath11k_base *ab,const struct wmi_pdev_csa_switch_ev *ev, const u32 *vdev_ids) { - int i; + u32 vdev_ids_len = ath11k_wmi_tlv_data_len(vdev_ids); +u32 num_vdevs = ev->num_vdevs;struct ath11k_vif *arvif; +int i;/* Finish CSA once the switch count becomes NULL */ if (ev->current_switch_count)return ; +if (num_vdevs > vdev_ids_len /sizeof (*vdev_ids)) { +ath11k_warn (ab,"csa switch count num_vdevs %u exceeds tlv array length %u\n" , + num_vdevs, vdev_ids_len); +return ; + } +rcu_read_lock (); -for (i =0 ; i < ev->num_vdevs; i++) { +for (i =0 ; i < num_vdevs; i++) { arvif =ath11k_mac_get_arvif_by_vdev_id (ab, vdev_ids[i]);if (!arvif) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 929/1424 platform/chrome: cros_ec_debugfs: Clean up console log on probe failure
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hongyan Xu <[email protected]>
[ Upstream commit 5d187600c4603b8f7812b12ce359a11ad7a7fd3a ]
Add a dedicated error label for failures after successful console log setup.
--- drivers/platform/chrome/cros_ec_debugfs.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/platform/chrome/cros_ec_debugfs.c +3 -1
@@ -521,7 +521,7 @@ static int cros_ec_debugfs_probe(struct platform_device *pd) ret =blocking_notifier_chain_register (&ec->ec_dev->panic_notifier, &debug_info->notifier_panic);if (ret) - goto remove_debugfs; + goto cleanup_console_log; ec->debug_info = debug_info;
@@ -529,6 +529,8 @@ static int cros_ec_debugfs_probe(struct platform_device *pd)return 0 ; +cleanup_console_log: +cros_ec_cleanup_console_log (debug_info); remove_debugfs:debugfs_remove_recursive (debug_info->dir);return ret;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 930/1424 platform/chrome: cros_ec_debugfs: Unregister panic notifier
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hongyan Xu <[email protected]>
[ Upstream commit e5954d3031fb55dd31aa59bae477d63c68e941c0 ]
cros_ec_debugfs_probe() registers notifier_panic with the EC panic notifier chain. The remove path tears down debugfs and the console log, but leaves the notifier registered. A later panic notification can call back into the removed instance and queue work that accesses released data.
Unregister the panic notifier before tearing down the debugfs and console log state.
This issue was found by a static analysis tool.
--- drivers/platform/chrome/cros_ec_debugfs.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/platform/chrome/cros_ec_debugfs.c +2 -0
@@ -540,6 +540,8 @@ static int cros_ec_debugfs_remove(struct platform_device *pd) {struct cros_ec_dev *ec =dev_get_drvdata (pd->dev.parent); +blocking_notifier_chain_unregister (&ec->ec_dev->panic_notifier, + &ec->debug_info->notifier_panic);debugfs_remove_recursive (ec->debug_info->dir);cros_ec_cleanup_console_log (ec->debug_info);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 931/1424 wifi: rtlwifi: pci: fix error path in rtl_pci_probe()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Abdun Nihaal <[email protected]>
[ Upstream commit 3c2999d13eeb222ae56631aeb7ca248090f2b210 ]
In the last error path in rtl_pci_probe(), the cleanup functions are skipped due to a wrong goto label. Moreover, the successful call to rtl_init_rfkill(), ieee80211_register_hw(), rtl_debug_add_one() have to be reverted. Fix this issue by updating the labels and adding the relevant cleanup functions to the last error path.
--- drivers/net/wireless/realtek/rtlwifi/pci.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/net/wireless/realtek/rtlwifi/pci.c +5 -1
@@ -2228,13 +2228,17 @@ int rtl_pci_probe(struct pci_dev *pdev,rtl_dbg (rtlpriv,COMP_INIT ,DBG_DMESG ,"%s: failed to register IRQ handler\n" ,wiphy_name (hw->wiphy)); - goto fail3; + goto fail6; } rtlpci->irq_alloc =1 ;set_bit (RTL_STATUS_INTERFACE_START , &rtlpriv->status);return 0 ; +fail6: +rtl_deinit_rfkill (hw); +rtl_debug_remove_one (hw); +ieee80211_unregister_hw (hw); fail5:rtl_pci_deinit (hw); fail4:
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 932/1424 bus: mhi: host: Flush the posted write after writing to MHI_SOC_RESET_REQ_OFFSET
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Manivannan Sadhasivam <[email protected]>
[ Upstream commit 24f4423cbc89548def2b05ae86de6175086dbf94 ]
mhi_soc_reset() tries to reset the device by writing to the MHI_SOC_RESET_REQ_OFFSET register. But it doesn't do a read-back to ensure that the write gets flushed to the device before returning to the caller.
This may lead to the delay (if implemented) on the caller to be insufficient, if the posted write doesn't reach the device before the delay.
So add a read-back after writing to the MHI_SOC_RESET_REQ_OFFSET register.
--- drivers/bus/mhi/host/main.c | 6 ++++++ 1 file changed, 6 insertions(+)
drivers/bus/mhi/host/main.c +6 -0
@@ -168,6 +168,9 @@ EXPORT_SYMBOL_GPL(mhi_get_mhi_state);void mhi_soc_reset (struct mhi_controller *mhi_cntrl) { +int __maybe_unused ret; +u32 tmp; +if (mhi_cntrl->reset) { mhi_cntrl->reset (mhi_cntrl);return ;
@@ -176,6 +179,9 @@ void mhi_soc_reset(struct mhi_controller *mhi_cntrl)/* Generic MHI SoC reset */ mhi_write_reg (mhi_cntrl, mhi_cntrl->regs,MHI_SOC_RESET_REQ_OFFSET ,MHI_SOC_RESET_REQ ); +/* Flush the posted write to the device (ignore return value) */ + ret =mhi_read_reg (mhi_cntrl, mhi_cntrl->regs,MHI_SOC_RESET_REQ_OFFSET , + &tmp); }EXPORT_SYMBOL_GPL (mhi_soc_reset);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 933/1424 md/raid5: protect bitmap batch counters aka seq_flush/seq_write consistency
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chen Cheng <[email protected]>
[ Upstream commit f565925810cb8bc799421485770e15d922ef766a ]
kcsan detect race :
- raid5d() closes the current bitmap batch by updating
conf->seq_flush under conf->device_lock. - __add_stripe_bio() read conf->seq_flush without that lock when assigning sh->bm_seq.
so, protect seq_flush/seq_write consistency for multiple CPUs by READ_ONCE()/WRITE_ONCE() under the path without held device_lock.
re-explain the stripe batch sequence number update flow:
1. sh->bm_seq declare which batch number the stripe belongs to when perform bitmap-related write.
==> bm_seq = seq_flush+1
2. stripe be handled,
* if sh->bm_seq - conf->seq_write > 0, means the batch stripes **newer than** the last written batch, it cannot proceed yet, queued on bitmap_list.
* otherwise , has already proceed.
3. raid5d() ++seq_flush to closes the current batch, means
* no more stripes join that old batch
* just-closed batch ready to write-out to disk
4. raid5d() calls bitmap hooks unplug() or writeout, then, ++seq_write to the same as bm_seq.
- seq_flush - for producer, to close batches.
- seq_write - for consumer, the checkpoint number.
the report:
====================================
BUG: KCSAN: data-race in __add_stripe_bio / raid5d
write to 0xffff88ba5625d470 of 4 bytes by task 82401 on cpu 0:
raid5d+0x1d9/0xba0 [.....]
read to 0xffff88ba5625d470 of 4 bytes by task 82421 on cpu 8:
__add_stripe_bio+0x332/0x400 raid5_make_request+0x6ac/0x2930 md_handle_request+0x4a2/0xa40 md_submit_bio+0x109/0x1a0 __submit_bio+0x2ec/0x390 [.....]
v1 -> v2:
- remove WRITE_ONCE(conf->seq_write) in held device_lock path.
- remove READ_ONCE(conf->seq_flush) in held device_lock path.
--- drivers/md/raid5.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
drivers/md/raid5.c +6 -4
@@ -3587,7 +3587,7 @@ static void __add_stripe_bio(struct stripe_head *sh, struct bio *bi, sh->dev[dd_idx].sector);if (conf->mddev->bitmap && firstwrite && !sh->batch_head) { - sh->bm_seq = conf->seq_flush+1 ; + sh->bm_seq =READ_ONCE (conf->seq_flush) +1 ;set_bit (STRIPE_BIT_DELAY , &sh->state); } }
@@ -5807,7 +5807,7 @@ static void make_discard_request(struct mddev *mddev, struct bio *bi) }spin_unlock_irq (&sh->stripe_lock);if (conf->mddev->bitmap) { - sh->bm_seq = conf->seq_flush +1 ; + sh->bm_seq =READ_ONCE (conf->seq_flush) +1 ;set_bit (STRIPE_BIT_DELAY , &sh->state); }
@@ -6847,11 +6847,13 @@ static void raid5d(struct md_thread *thread)if ( !list_empty (&conf->bitmap_list)) {/* Now is a good time to flush some bitmap updates */ - conf->seq_flush++; +int seq = conf->seq_flush +1 ; + +WRITE_ONCE (conf->seq_flush, seq);spin_unlock_irq (&conf->device_lock);md_bitmap_unplug (mddev->bitmap);spin_lock_irq (&conf->device_lock); - conf->seq_write = conf->seq_flush; + conf->seq_write = seq;activate_bit_delay (conf, conf->temp_inactive_list); }raid5_activate_delayed (conf);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 934/1424 md/raid5-ppl: fix use-after-free in ppl_do_flush()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sajal Gupta <[email protected]>
[ Upstream commit 371f7a1b392edc8b7cf449cc7713179b588f2d0e ]
The loop in ppl_do_flush() continues iterating after calling ppl_io_unit_finished(), touching io->pending_flushes and leading to a use-after-free.
Add a break statement to stop the loop once io is freed.
--- drivers/md/raid5-ppl.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/md/raid5-ppl.c +3 -1
@@ -645,8 +645,10 @@ static void ppl_do_flush(struct ppl_io_unit *io) log->disk_flush_bitmap =0 ;for (i = flushed_disks ; i < raid_disks; i++) { -if (atomic_dec_and_test (&io->pending_flushes)) +if (atomic_dec_and_test (&io->pending_flushes)) {ppl_io_unit_finished (io); +break ; + } } }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 935/1424 tools/nolibc/powerpc: mark ctr and xer as clobbered by system call
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thomas Weißschuh <[email protected]>
[ Upstream commit b9fc5a1742b0c8fb7edf066cc17fa0b18b7be623 ]
The system call can clobber the ctr and xer registers.
Make sure the compiler takes this into account.
The missing clobbers only seem to be an issue with newer compilers.
--- tools/include/nolibc/arch-powerpc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/include/nolibc/arch-powerpc.h +1 -1
@@ -23,7 +23,7 @@*/ #define _NOLIBC_SYSCALL_CLOBBERLIST \ - "memory", "cr0", "r12", "r11", "r10", "r9" + "memory", "cr0", "ctr", "xer", "r12", "r11", "r10", "r9"#define my_syscall0 (num) \ ({ \
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 936/1424 selftests/zram: fix kernel_gte() for POSIX sh
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cheng-Han Wu <[email protected]>
[ Upstream commit 649ba27dfac784427a01f9c95c09ecbcb88900d8 ]
Commit fc4eb486a59d ("selftests/zram: Skip max_comp_streams interface on newer kernel") added kernel_gte() to zram_lib.sh. The function uses the bash-specific [[ ... ]] conditional, but zram selftests source this file while running under /bin/sh.
On systems where /bin/sh is dash, such as Debian, the following test fails:
dash -c '
kernel_major=6; kernel_minor=1; major=6; minor=0
if [ $kernel_major -gt $major ]; then
echo ok
elif [[ $kernel_major -eq $major && $kernel_minor -ge $minor ]]; then
echo ok
fi'with:
dash: 5: [[: not found
Use separate POSIX test expressions joined by && instead.
--- tools/testing/selftests/zram/zram_lib.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/testing/selftests/zram/zram_lib.sh +1 -1
@@ -37,7 +37,7 @@ kernel_gte() if [ $kernel_major -gt $major ]; then return 0 - elif [[ $kernel_major -eq $major && $kernel_minor -ge $minor ]]; then + elif [ $kernel_major -eq $major ] && [ $kernel_minor -ge $minor ]; then return 0 fi
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 937/1424 rcu: Remove unused function declaration rcu_eqs_special_set()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yue Haibing <[email protected]>
[ Upstream commit b93c5fe16e4aa177cd072c1c4652cbe1b19a7812 ]
Commit a86baa69c2b7 ("rcu: Remove special bit at the bottom of the ->dynticks counter") left behind this, remove it.
Stable-dep-of: 27d73e81195b ("rcu: Mark accesses to ->rcu_urgent_qs and ->rcu_need_heavy_qs")
--- include/linux/rcutree.h | 1 - 1 file changed, 1 deletion(-)
include/linux/rcutree.h +0 -1
@@ -37,7 +37,6 @@ void synchronize_rcu_expedited(void);void kvfree_call_rcu (struct rcu_head *head,void *ptr);void rcu_barrier (void ); -bool rcu_eqs_special_set (int cpu);void rcu_momentary_dyntick_idle (void );void kfree_rcu_scheduler_running (void );bool rcu_gp_might_be_stalled (void );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 938/1424 rcu: Rename rcu_momentary_dyntick_idle() into rcu_momentary_eqs()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Valentin Schneider <[email protected]>
[ Upstream commit 32a9f26e5e266f0116cc8536e5e4544523ddd334 ]
The context_tracking.state RCU_DYNTICKS subvariable has been renamed to RCU_WATCHING, replace "dyntick_idle" into "eqs" to drop the dyntick reference.
Stable-dep-of: 27d73e81195b ("rcu: Mark accesses to ->rcu_urgent_qs and ->rcu_need_heavy_qs")
--- include/linux/rcutiny.h | 2 +- include/linux/rcutree.h | 2 +- kernel/rcu/rcutorture.c | 4 ++-- kernel/rcu/tree.c | 4 ++-- kernel/rcu/tree_nocb.h | 2 +- kernel/rcu/tree_plugin.h | 6 +++--- kernel/stop_machine.c | 2 +- kernel/trace/trace_osnoise.c | 4 ++-- 8 files changed, 13 insertions(+), 13 deletions(-)
include/linux/rcutiny.h +1 -1
@@ -158,7 +158,7 @@ void rcu_scheduler_starting(void);static inline void rcu_end_inkernel_boot (void ) { }static inline bool rcu_inkernel_boot_has_ended (void ) {return true; }static inline bool rcu_is_watching (void ) {return true; } -static inline void rcu_momentary_dyntick_idle (void ) { } +static inline void rcu_momentary_eqs (void ) { }static inline void kfree_rcu_scheduler_running (void ) { }static inline bool rcu_gp_might_be_stalled (void ) {return false; }
include/linux/rcutree.h +1 -1
@@ -37,7 +37,7 @@ void synchronize_rcu_expedited(void);void kvfree_call_rcu (struct rcu_head *head,void *ptr);void rcu_barrier (void ); -void rcu_momentary_dyntick_idle (void ); +void rcu_momentary_eqs (void );void kfree_rcu_scheduler_running (void );bool rcu_gp_might_be_stalled (void );
kernel/rcu/rcutorture.c +2 -2
@@ -2641,7 +2641,7 @@ static unsigned long rcu_torture_fwd_prog_cbfree(struct rcu_fwd *rfp)rcu_torture_fwd_prog_cond_resched (freed);if (tick_nohz_full_enabled ()) {local_irq_save (flags); -rcu_momentary_dyntick_idle (); +rcu_momentary_eqs ();local_irq_restore (flags); } }
@@ -2791,7 +2791,7 @@ static void rcu_torture_fwd_prog_cr(struct rcu_fwd *rfp)rcu_torture_fwd_prog_cond_resched (n_launders + n_max_cbs);if (tick_nohz_full_enabled ()) {local_irq_save (flags); -rcu_momentary_dyntick_idle (); +rcu_momentary_eqs ();local_irq_restore (flags); } }
kernel/rcu/tree.c +2 -2
@@ -323,7 +323,7 @@ bool rcu_dynticks_zero_in_eqs(int cpu, int *vp)* * The caller must have disabled interrupts and must not be idle. */ -notrace void rcu_momentary_dyntick_idle(void) +notrace void rcu_momentary_eqs(void) {int seq;
@@ -333,7 +333,7 @@ notrace void rcu_momentary_dyntick_idle(void)WARN_ON_ONCE (!(seq &RCU_DYNTICKS_IDX ));rcu_preempt_deferred_qs (current); } -EXPORT_SYMBOL_GPL (rcu_momentary_dyntick_idle); +EXPORT_SYMBOL_GPL (rcu_momentary_eqs);/** * rcu_is_cpu_rrupt_from_idle - see if 'interrupted' from idle
kernel/rcu/tree_nocb.h +1 -1
@@ -930,7 +930,7 @@ static void nocb_cb_wait(struct rcu_data *rdp)local_irq_save (flags); -rcu_momentary_dyntick_idle (); +rcu_momentary_eqs ();local_irq_restore (flags);/* * Disable BH to provide the expected environment. Also, when
kernel/rcu/tree_plugin.h +3 -3
@@ -953,7 +953,7 @@ static void rcu_qs(void)/* * Register an urgently needed quiescent state. If there is an -* emergency, invoke rcu_momentary_dyntick_idle() to do a heavy-weight +* emergency, invoke rcu_momentary_eqs() to do a heavy-weight * dyntick-idle quiescent state visible to other CPUs, which will in * some cases serve for expedited as well as normal grace periods. * Either way, register a lightweight quiescent state.
@@ -973,7 +973,7 @@ void rcu_all_qs(void)this_cpu_write (rcu_data.rcu_urgent_qs, false);if (unlikely (raw_cpu_read (rcu_data.rcu_need_heavy_qs))) {local_irq_save (flags); -rcu_momentary_dyntick_idle (); +rcu_momentary_eqs ();local_irq_restore (flags); }rcu_qs ();
@@ -993,7 +993,7 @@ void rcu_note_context_switch(bool preempt) goto out;this_cpu_write (rcu_data.rcu_urgent_qs, false);if (unlikely (raw_cpu_read (rcu_data.rcu_need_heavy_qs))) -rcu_momentary_dyntick_idle (); +rcu_momentary_eqs (); out:rcu_tasks_qs (current, preempt);trace_rcu_utilization (TPS ("End context switch" ));
kernel/stop_machine.c +1 -1
@@ -251,7 +251,7 @@ static int multi_cpu_stop(void *data)*/ touch_nmi_watchdog (); } -rcu_momentary_dyntick_idle (); +rcu_momentary_eqs (); }while (curstate !=MULTI_STOP_EXIT );local_irq_restore (flags);
kernel/trace/trace_osnoise.c +2 -2
@@ -1554,7 +1554,7 @@ static int run_osnoise(void)* This will eventually cause unwarranted noise as PREEMPT_RCU * will force preemption as the means of ending the current * grace period. We avoid this problem by calling -* rcu_momentary_dyntick_idle(), which performs a zero duration +* rcu_momentary_eqs(), which performs a zero duration * EQS allowing PREEMPT_RCU to end the current grace period. * This call shouldn't be wrapped inside an RCU critical * section.
@@ -1566,7 +1566,7 @@ static int run_osnoise(void)if (!disable_irq)local_irq_disable (); -rcu_momentary_dyntick_idle (); +rcu_momentary_eqs ();if (!disable_irq)local_irq_enable ();
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 939/1424 rcu: Mark accesses to ->rcu_urgent_qs and ->rcu_need_heavy_qs
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Itai Handler <[email protected]>
[ Upstream commit 27d73e81195b395270117ff77c47be2ed9b09b12 ]
rcu_all_qs() and rcu_note_context_switch() read/clear the per-CPU ->rcu_urgent_qs and ->rcu_need_heavy_qs flags with plain raw_cpu_read() and this_cpu_write(), while the RCU core clears them with WRITE_ONCE() in rcu_disable_urgency_upon_qs(). KCSAN flags the resulting same-CPU race:
BUG: KCSAN: data-race in rcu_all_qs / rcu_disable_urgency_upon_qs
It is benign -- the flags are advisory and rcu_all_qs() re-reads ->rcu_urgent_qs with smp_load_acquire() before acting on it -- but these are the last unmarked accesses to the two flags; every other access already uses READ_ONCE()/WRITE_ONCE()/smp_*. Mark them to match. No functional change.
Reproduced on a PREEMPT_NONE, CONFIG_KCSAN_INTERRUPT_WATCHER=y kernel with a pthreads program whose threads (two per CPU) loop reading a large file:
for (;;) {
int fd = open("/proc/kallsyms", O_RDONLY);
while (read(fd, buf, sizeof(buf)) > 0)
;
close(fd);
}The read()s drive cond_resched() -> rcu_all_qs() while the busy CPUs keep the grace period urgent, so the RCU core clears the flags concurrently.
--- kernel/rcu/tree_plugin.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
kernel/rcu/tree_plugin.h +5 -5
@@ -962,7 +962,7 @@ void rcu_all_qs(void) {unsigned long flags; -if (!raw_cpu_read (rcu_data.rcu_urgent_qs)) +if (!READ_ONCE (*raw_cpu_ptr (&rcu_data.rcu_urgent_qs)))return ;preempt_disable ();// For CONFIG_PREEMPT_COUNT=y kernels /* Load rcu_urgent_qs before other flags. */
@@ -970,8 +970,8 @@ void rcu_all_qs(void)preempt_enable ();return ; } -this_cpu_write (rcu_data.rcu_urgent_qs, false); -if (unlikely (raw_cpu_read (rcu_data.rcu_need_heavy_qs))) { +WRITE_ONCE (*this_cpu_ptr (&rcu_data.rcu_urgent_qs), false); +if (unlikely (READ_ONCE (*this_cpu_ptr (&rcu_data.rcu_need_heavy_qs)))) {local_irq_save (flags);rcu_momentary_eqs ();local_irq_restore (flags);
@@ -991,8 +991,8 @@ void rcu_note_context_switch(bool preempt)/* Load rcu_urgent_qs before other flags. */ if (!smp_load_acquire (this_cpu_ptr (&rcu_data.rcu_urgent_qs))) goto out; -this_cpu_write (rcu_data.rcu_urgent_qs, false); -if (unlikely (raw_cpu_read (rcu_data.rcu_need_heavy_qs))) +WRITE_ONCE (*this_cpu_ptr (&rcu_data.rcu_urgent_qs), false); +if (unlikely (READ_ONCE (*this_cpu_ptr (&rcu_data.rcu_need_heavy_qs))))rcu_momentary_eqs (); out:rcu_tasks_qs (current, preempt);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 940/1424 arm64: dts: qcom: msm8998: Dont pull-up I2C pins by default in sleep
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Konrad Dybcio <[email protected]>
[ Upstream commit 58ce9a2b9099bb26aed55d4e350c32af94930532 ]
When the I2C controller is disabled, no communication is expected to take place. Without traffic on the bus, the pull-up is unnecessary.
Both the vendor kernel for this platform and DTs of other SoCs in upstream concur this logic. Change the default and clean up now-NOP overrides.
--- .../dts/qcom/msm8998-sony-xperia-yoshino.dtsi | 4 ---- .../boot/dts/qcom/msm8998-xiaomi-sagit.dts | 5 ---- arch/arm64/boot/dts/qcom/msm8998.dtsi | 24 +++++++++---------- 3 files changed, 12 insertions(+), 21 deletions(-)
arch/arm64/boot/dts/qcom/msm8998-sony-xperia-yoshino.dtsi +0 -4
@@ -224,10 +224,6 @@ rmi4-f11@11 { }; }; -&blsp1_i2c5_sleep { - bias-disable; -}; - &blsp1_uart3 { status = "okay";
arch/arm64/boot/dts/qcom/msm8998-xiaomi-sagit.dts +0 -5
@@ -217,11 +217,6 @@ rmi4-f1a@1a { }; }; -&blsp1_i2c5_sleep { - /delete-property/ bias-pull-up; - bias-disable; -}; - &blsp1_uart3 { status = "okay";
arch/arm64/boot/dts/qcom/msm8998.dtsi +12 -12
@@ -1183,7 +1183,7 @@ blsp1_i2c1_sleep: blsp1-i2c1-sleep-state-state { pins = "gpio2", "gpio3"; function = "blsp_i2c1"; drive-strength = <2>; - bias-pull-up; + bias-disable; }; blsp1_i2c2_default: blsp1-i2c2-default-state {
@@ -1197,7 +1197,7 @@ blsp1_i2c2_sleep: blsp1-i2c2-sleep-state-state { pins = "gpio32", "gpio33"; function = "blsp_i2c2"; drive-strength = <2>; - bias-pull-up; + bias-disable; }; blsp1_i2c3_default: blsp1-i2c3-default-state {
@@ -1211,7 +1211,7 @@ blsp1_i2c3_sleep: blsp1-i2c3-sleep-state { pins = "gpio47", "gpio48"; function = "blsp_i2c3"; drive-strength = <2>; - bias-pull-up; + bias-disable; }; blsp1_i2c4_default: blsp1-i2c4-default-state {
@@ -1225,7 +1225,7 @@ blsp1_i2c4_sleep: blsp1-i2c4-sleep-state { pins = "gpio10", "gpio11"; function = "blsp_i2c4"; drive-strength = <2>; - bias-pull-up; + bias-disable; }; blsp1_i2c5_default: blsp1-i2c5-default-state {
@@ -1239,7 +1239,7 @@ blsp1_i2c5_sleep: blsp1-i2c5-sleep-state { pins = "gpio87", "gpio88"; function = "blsp_i2c5"; drive-strength = <2>; - bias-pull-up; + bias-disable; }; blsp1_i2c6_default: blsp1-i2c6-default-state {
@@ -1253,7 +1253,7 @@ blsp1_i2c6_sleep: blsp1-i2c6-sleep-state { pins = "gpio43", "gpio44"; function = "blsp_i2c6"; drive-strength = <2>; - bias-pull-up; + bias-disable; }; blsp1_spi_b_default: blsp1-spi-b-default-state {
@@ -1318,7 +1318,7 @@ blsp2_i2c1_sleep: blsp2-i2c1-sleep-state { pins = "gpio55", "gpio56"; function = "blsp_i2c7"; drive-strength = <2>; - bias-pull-up; + bias-disable; }; blsp2_i2c2_default: blsp2-i2c2-default-state {
@@ -1332,7 +1332,7 @@ blsp2_i2c2_sleep: blsp2-i2c2-sleep-state { pins = "gpio6", "gpio7"; function = "blsp_i2c8"; drive-strength = <2>; - bias-pull-up; + bias-disable; }; blsp2_i2c3_default: blsp2-i2c3-default-state {
@@ -1346,7 +1346,7 @@ blsp2_i2c3_sleep: blsp2-i2c3-sleep-state { pins = "gpio51", "gpio52"; function = "blsp_i2c9"; drive-strength = <2>; - bias-pull-up; + bias-disable; }; blsp2_i2c4_default: blsp2-i2c4-default-state {
@@ -1360,7 +1360,7 @@ blsp2_i2c4_sleep: blsp2-i2c4-sleep-state { pins = "gpio67", "gpio68"; function = "blsp_i2c10"; drive-strength = <2>; - bias-pull-up; + bias-disable; }; blsp2_i2c5_default: blsp2-i2c5-default-state {
@@ -1374,7 +1374,7 @@ blsp2_i2c5_sleep: blsp2-i2c5-sleep-state { pins = "gpio60", "gpio61"; function = "blsp_i2c11"; drive-strength = <2>; - bias-pull-up; + bias-disable; }; blsp2_i2c6_default: blsp2-i2c6-default-state {
@@ -1388,7 +1388,7 @@ blsp2_i2c6_sleep: blsp2-i2c6-sleep-state { pins = "gpio83", "gpio84"; function = "blsp_i2c12"; drive-strength = <2>; - bias-pull-up; + bias-disable; }; blsp2_spi1_default: blsp2-spi1-default-state {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 941/1424 arm64: dts: qcom: sdm632-motorola-ocean: Fix LED default trigger property
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Konrad Dybcio <[email protected]>
[ Upstream commit c82ea31fb783d9ce4080eca1a7bb855f4648fc28 ]
The correct property name is "linux,default-trigger", not "default-trigger". Fix it to avoid DT checker warnings and let the OSes consume the intended information.
--- arch/arm64/boot/dts/qcom/sdm632-motorola-ocean.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm64/boot/dts/qcom/sdm632-motorola-ocean.dts +1 -1
@@ -130,7 +130,7 @@ led-controller@36 { led: led@1 { reg = <1>; - default-trigger = "backlight"; + linux,default-trigger = "backlight"; function = LED_FUNCTION_BACKLIGHT; led-sources = <0 1 2>; };
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 942/1424 clk: qcom: gcc-qcm2290: dont park QUP RCGs upon registration
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Baryshkov <[email protected]>
[ Upstream commit 9c4cee964e0ccc155e4ab8fa6cec88fffc262c63 ]
The gcc_qupv3_wrap0_s[0-5]_clk_src RCGs feed the QUP serial engines (UART/I2C/SPI). Since shared RCGs are parked to XO at registration time, binding the gcc-qcm2290 driver reprograms these clocks away from the rate configured by the bootloader. For the UART used as the boot console this drops early console output until the serial driver later reconfigures the clock.
Switch the QUP wrap0 clock sources over to clk_rcg2_shared_no_init_park_ops so their frequency is left unchanged at registration time, keeping the bootloader-configured console working across the gcc driver probe.
--- drivers/clk/qcom/gcc-qcm2290.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
drivers/clk/qcom/gcc-qcm2290.c +6 -6
@@ -1082,7 +1082,7 @@ static struct clk_init_data gcc_qupv3_wrap0_s0_clk_src_init = { .name = "gcc_qupv3_wrap0_s0_clk_src", .parent_data = gcc_parents_1, .num_parents = ARRAY_SIZE(gcc_parents_1), - .ops = &clk_rcg2_shared_ops, + .ops = &clk_rcg2_shared_no_init_park_ops, };static struct clk_rcg2 gcc_qupv3_wrap0_s0_clk_src = {
@@ -1098,7 +1098,7 @@ static struct clk_init_data gcc_qupv3_wrap0_s1_clk_src_init = { .name = "gcc_qupv3_wrap0_s1_clk_src", .parent_data = gcc_parents_1, .num_parents = ARRAY_SIZE(gcc_parents_1), - .ops = &clk_rcg2_shared_ops, + .ops = &clk_rcg2_shared_no_init_park_ops, };static struct clk_rcg2 gcc_qupv3_wrap0_s1_clk_src = {
@@ -1114,7 +1114,7 @@ static struct clk_init_data gcc_qupv3_wrap0_s2_clk_src_init = { .name = "gcc_qupv3_wrap0_s2_clk_src", .parent_data = gcc_parents_1, .num_parents = ARRAY_SIZE(gcc_parents_1), - .ops = &clk_rcg2_shared_ops, + .ops = &clk_rcg2_shared_no_init_park_ops, };static struct clk_rcg2 gcc_qupv3_wrap0_s2_clk_src = {
@@ -1130,7 +1130,7 @@ static struct clk_init_data gcc_qupv3_wrap0_s3_clk_src_init = { .name = "gcc_qupv3_wrap0_s3_clk_src", .parent_data = gcc_parents_1, .num_parents = ARRAY_SIZE(gcc_parents_1), - .ops = &clk_rcg2_shared_ops, + .ops = &clk_rcg2_shared_no_init_park_ops, };static struct clk_rcg2 gcc_qupv3_wrap0_s3_clk_src = {
@@ -1146,7 +1146,7 @@ static struct clk_init_data gcc_qupv3_wrap0_s4_clk_src_init = { .name = "gcc_qupv3_wrap0_s4_clk_src", .parent_data = gcc_parents_1, .num_parents = ARRAY_SIZE(gcc_parents_1), - .ops = &clk_rcg2_shared_ops, + .ops = &clk_rcg2_shared_no_init_park_ops, };static struct clk_rcg2 gcc_qupv3_wrap0_s4_clk_src = {
@@ -1162,7 +1162,7 @@ static struct clk_init_data gcc_qupv3_wrap0_s5_clk_src_init = { .name = "gcc_qupv3_wrap0_s5_clk_src", .parent_data = gcc_parents_1, .num_parents = ARRAY_SIZE(gcc_parents_1), - .ops = &clk_rcg2_shared_ops, + .ops = &clk_rcg2_shared_no_init_park_ops, };static struct clk_rcg2 gcc_qupv3_wrap0_s5_clk_src = {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 943/1424 arm64: dts: qcom: sc8280xp-crd: Fix the pin index for misc_3p3_reg_en
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Konrad Dybcio <[email protected]>
[ Upstream commit 0e05c183f3b97427f00d619132ba5984494f6886 ]
The correct pin is GPIO1. Fix it.
--- arch/arm64/boot/dts/qcom/sc8280xp-crd.dts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/arm64/boot/dts/qcom/sc8280xp-crd.dts +2 -2
@@ -167,7 +167,7 @@ vreg_misc_3p3: regulator-misc-3p3 { regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; - gpio = <&pmc8280_1_gpios 2 GPIO_ACTIVE_HIGH>; + gpio = <&pmc8280_1_gpios 1 GPIO_ACTIVE_HIGH>; enable-active-high; pinctrl-names = "default";
@@ -757,7 +757,7 @@ edp_bl_reg_en: edp-bl-reg-en-state { }; misc_3p3_reg_en: misc-3p3-reg-en-state { - pins = "gpio2"; + pins = "gpio1"; function = "normal"; }; };
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 944/1424 arm64: dts: qcom: sm8250-xiaomi-elish: correct the board ID
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dawid Wróbel <[email protected]>
[ Upstream commit 299731d4fbeaaa141ce2e8226ca00cb30d6ab647 ]
elish declares the same qcom,msm-id and qcom,board-id pair as sm8250-sony-xperia-edo.dtsi, so a bootloader choosing between appended device trees cannot tell the two boards apart.
0x10008 is Sony's value. The downstream device tree for this board, elish-sm8250-overlay.dts, uses qcom,board-id = <47 0>, i.e. platform type 0x2f.
--- arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-common.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm64/boot/dts/qcom/sm8250-xiaomi-elish-common.dtsi +1 -1
@@ -27,7 +27,7 @@ / { /* required for bootloader to select correct board */ qcom,msm-id = <QCOM_ID_SM8250 0x20001>; /* SM8250 v2.1 */ - qcom,board-id = <0x10008 0>; + qcom,board-id = <0x2f 0>; chosen { #address-cells = <2>;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 945/1424 arm64: dts: qcom: sc8180x: drop duplicated PCI iommus property
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Krzysztof Kozlowski <[email protected]>
[ Upstream commit 2c21e5a84524381977b4744e906fb31862ac5809 ]
The IOMMUs for PCI controller on SC8180x are defined in iommu-map, so drop duplicared iommus:
sc8180x-lenovo-flex-5g.dtb: pci@1c08000: Unevaluated properties are not allowed ('iommus' was unexpected)
Stable-dep-of: a4548204821a ("arm64: dts: qcom: sc8180x: Fix the PCIe iommu-map entries")
--- arch/arm64/boot/dts/qcom/sc8180x.dtsi | 4 ---- 1 file changed, 4 deletions(-)
arch/arm64/boot/dts/qcom/sc8180x.dtsi +0 -4
@@ -1745,7 +1745,6 @@ pcie0: pci@1c00000 { assigned-clocks = <&gcc GCC_PCIE_0_AUX_CLK>; assigned-clock-rates = <19200000>; - iommus = <&apps_smmu 0x1d80 0x7f>; iommu-map = <0x0 &apps_smmu 0x1d80 0x1>, <0x100 &apps_smmu 0x1d81 0x1>;
@@ -1843,7 +1842,6 @@ pcie3: pci@1c08000 { assigned-clocks = <&gcc GCC_PCIE_3_AUX_CLK>; assigned-clock-rates = <19200000>; - iommus = <&apps_smmu 0x1e00 0x7f>; iommu-map = <0x0 &apps_smmu 0x1e00 0x1>, <0x100 &apps_smmu 0x1e01 0x1>;
@@ -1942,7 +1940,6 @@ pcie1: pci@1c10000 { assigned-clocks = <&gcc GCC_PCIE_1_AUX_CLK>; assigned-clock-rates = <19200000>; - iommus = <&apps_smmu 0x1c80 0x7f>; iommu-map = <0x0 &apps_smmu 0x1c80 0x1>, <0x100 &apps_smmu 0x1c81 0x1>;
@@ -2041,7 +2038,6 @@ pcie2: pci@1c18000 { assigned-clocks = <&gcc GCC_PCIE_2_AUX_CLK>; assigned-clock-rates = <19200000>; - iommus = <&apps_smmu 0x1d00 0x7f>; iommu-map = <0x0 &apps_smmu 0x1d00 0x1>, <0x100 &apps_smmu 0x1d01 0x1>;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 946/1424 arm64: dts: qcom: sc8180x: Fix the PCIe iommu-map entries
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Manivannan Sadhasivam <[email protected]>
[ Upstream commit a4548204821a56c23cd711cfad2a637ca055ff47 ]
The IOMMU provider apps_smmu uses '#iommu-cells = <2>', but the PCIe iommu-map entries specify only one cell for the SID, omitting the SID mask. This went unnoticed until the OF core started warning with commit ccb2fd725d41 ("of: Respect #{iommu,msi}-cells in maps"):
iommu-map has 1-cell entries targeting 2-cell #iommu-cells, treating as 1-cell output
So fix the entries to match the provider's '#iommu-cells' property.
--- arch/arm64/boot/dts/qcom/sc8180x.dtsi | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-)
arch/arm64/boot/dts/qcom/sc8180x.dtsi +8 -8
@@ -1745,8 +1745,8 @@ pcie0: pci@1c00000 { assigned-clocks = <&gcc GCC_PCIE_0_AUX_CLK>; assigned-clock-rates = <19200000>; - iommu-map = <0x0 &apps_smmu 0x1d80 0x1>, - <0x100 &apps_smmu 0x1d81 0x1>; + iommu-map = <0x0 &apps_smmu 0x1d80 0x0 0x1>, + <0x100 &apps_smmu 0x1d81 0x0 0x1>; resets = <&gcc GCC_PCIE_0_BCR>; reset-names = "pci";
@@ -1842,8 +1842,8 @@ pcie3: pci@1c08000 { assigned-clocks = <&gcc GCC_PCIE_3_AUX_CLK>; assigned-clock-rates = <19200000>; - iommu-map = <0x0 &apps_smmu 0x1e00 0x1>, - <0x100 &apps_smmu 0x1e01 0x1>; + iommu-map = <0x0 &apps_smmu 0x1e00 0x0 0x1>, + <0x100 &apps_smmu 0x1e01 0x0 0x1>; resets = <&gcc GCC_PCIE_3_BCR>; reset-names = "pci";
@@ -1940,8 +1940,8 @@ pcie1: pci@1c10000 { assigned-clocks = <&gcc GCC_PCIE_1_AUX_CLK>; assigned-clock-rates = <19200000>; - iommu-map = <0x0 &apps_smmu 0x1c80 0x1>, - <0x100 &apps_smmu 0x1c81 0x1>; + iommu-map = <0x0 &apps_smmu 0x1c80 0x0 0x1>, + <0x100 &apps_smmu 0x1c81 0x0 0x1>; resets = <&gcc GCC_PCIE_1_BCR>; reset-names = "pci";
@@ -2038,8 +2038,8 @@ pcie2: pci@1c18000 { assigned-clocks = <&gcc GCC_PCIE_2_AUX_CLK>; assigned-clock-rates = <19200000>; - iommu-map = <0x0 &apps_smmu 0x1d00 0x1>, - <0x100 &apps_smmu 0x1d01 0x1>; + iommu-map = <0x0 &apps_smmu 0x1d00 0x0 0x1>, + <0x100 &apps_smmu 0x1d01 0x0 0x1>; resets = <&gcc GCC_PCIE_2_BCR>; reset-names = "pci";
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 947/1424 arm64: dts: qcom: sdm845: Fix the PCIe iommu-map entries
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Manivannan Sadhasivam <[email protected]>
[ Upstream commit deaea7e982bc353c8d3c406774970f16ed901adb ]
The IOMMU provider apps_smmu uses '#iommu-cells = <2>', but the PCIe iommu-map entries specify only one cell for the SID, omitting the SID mask. This went unnoticed until the OF core started warning with commit ccb2fd725d41 ("of: Respect #{iommu,msi}-cells in maps"):
iommu-map has 1-cell entries targeting 2-cell #iommu-cells, treating as 1-cell output
So fix the entries to match the provider's '#iommu-cells' property.
--- arch/arm64/boot/dts/qcom/sdm845.dtsi | 64 ++++++++++++++-------------- 1 file changed, 32 insertions(+), 32 deletions(-)
arch/arm64/boot/dts/qcom/sdm845.dtsi +32 -32
@@ -2349,22 +2349,22 @@ pcie0: pci@1c00000 { "slave_q2a", "tbu"; - iommu-map = <0x0 &apps_smmu 0x1c10 0x1>, - <0x100 &apps_smmu 0x1c11 0x1>, - <0x200 &apps_smmu 0x1c12 0x1>, - <0x300 &apps_smmu 0x1c13 0x1>, - <0x400 &apps_smmu 0x1c14 0x1>, - <0x500 &apps_smmu 0x1c15 0x1>, - <0x600 &apps_smmu 0x1c16 0x1>, - <0x700 &apps_smmu 0x1c17 0x1>, - <0x800 &apps_smmu 0x1c18 0x1>, - <0x900 &apps_smmu 0x1c19 0x1>, - <0xa00 &apps_smmu 0x1c1a 0x1>, - <0xb00 &apps_smmu 0x1c1b 0x1>, - <0xc00 &apps_smmu 0x1c1c 0x1>, - <0xd00 &apps_smmu 0x1c1d 0x1>, - <0xe00 &apps_smmu 0x1c1e 0x1>, - <0xf00 &apps_smmu 0x1c1f 0x1>; + iommu-map = <0x0 &apps_smmu 0x1c10 0x0 0x1>, + <0x100 &apps_smmu 0x1c11 0x0 0x1>, + <0x200 &apps_smmu 0x1c12 0x0 0x1>, + <0x300 &apps_smmu 0x1c13 0x0 0x1>, + <0x400 &apps_smmu 0x1c14 0x0 0x1>, + <0x500 &apps_smmu 0x1c15 0x0 0x1>, + <0x600 &apps_smmu 0x1c16 0x0 0x1>, + <0x700 &apps_smmu 0x1c17 0x0 0x1>, + <0x800 &apps_smmu 0x1c18 0x0 0x1>, + <0x900 &apps_smmu 0x1c19 0x0 0x1>, + <0xa00 &apps_smmu 0x1c1a 0x0 0x1>, + <0xb00 &apps_smmu 0x1c1b 0x0 0x1>, + <0xc00 &apps_smmu 0x1c1c 0x0 0x1>, + <0xd00 &apps_smmu 0x1c1d 0x0 0x1>, + <0xe00 &apps_smmu 0x1c1e 0x0 0x1>, + <0xf00 &apps_smmu 0x1c1f 0x0 0x1>; resets = <&gcc GCC_PCIE_0_BCR>; reset-names = "pci";
@@ -2459,22 +2459,22 @@ pcie1: pci@1c08000 { assigned-clocks = <&gcc GCC_PCIE_1_AUX_CLK>; assigned-clock-rates = <19200000>; - iommu-map = <0x0 &apps_smmu 0x1c00 0x1>, - <0x100 &apps_smmu 0x1c01 0x1>, - <0x200 &apps_smmu 0x1c02 0x1>, - <0x300 &apps_smmu 0x1c03 0x1>, - <0x400 &apps_smmu 0x1c04 0x1>, - <0x500 &apps_smmu 0x1c05 0x1>, - <0x600 &apps_smmu 0x1c06 0x1>, - <0x700 &apps_smmu 0x1c07 0x1>, - <0x800 &apps_smmu 0x1c08 0x1>, - <0x900 &apps_smmu 0x1c09 0x1>, - <0xa00 &apps_smmu 0x1c0a 0x1>, - <0xb00 &apps_smmu 0x1c0b 0x1>, - <0xc00 &apps_smmu 0x1c0c 0x1>, - <0xd00 &apps_smmu 0x1c0d 0x1>, - <0xe00 &apps_smmu 0x1c0e 0x1>, - <0xf00 &apps_smmu 0x1c0f 0x1>; + iommu-map = <0x0 &apps_smmu 0x1c00 0x0 0x1>, + <0x100 &apps_smmu 0x1c01 0x0 0x1>, + <0x200 &apps_smmu 0x1c02 0x0 0x1>, + <0x300 &apps_smmu 0x1c03 0x0 0x1>, + <0x400 &apps_smmu 0x1c04 0x0 0x1>, + <0x500 &apps_smmu 0x1c05 0x0 0x1>, + <0x600 &apps_smmu 0x1c06 0x0 0x1>, + <0x700 &apps_smmu 0x1c07 0x0 0x1>, + <0x800 &apps_smmu 0x1c08 0x0 0x1>, + <0x900 &apps_smmu 0x1c09 0x0 0x1>, + <0xa00 &apps_smmu 0x1c0a 0x0 0x1>, + <0xb00 &apps_smmu 0x1c0b 0x0 0x1>, + <0xc00 &apps_smmu 0x1c0c 0x0 0x1>, + <0xd00 &apps_smmu 0x1c0d 0x0 0x1>, + <0xe00 &apps_smmu 0x1c0e 0x0 0x1>, + <0xf00 &apps_smmu 0x1c0f 0x0 0x1>; resets = <&gcc GCC_PCIE_1_BCR>; reset-names = "pci";
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 948/1424 arm64: dts: qcom: sm8150: Fix the PCIe iommu-map entries
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Manivannan Sadhasivam <[email protected]>
[ Upstream commit d2e56fb42e3d10d7e711063cdc00523ddb31d544 ]
The IOMMU provider apps_smmu uses '#iommu-cells = <2>', but the PCIe iommu-map entries specify only one cell for the SID, omitting the SID mask. This went unnoticed until the OF core started warning with commit ccb2fd725d41 ("of: Respect #{iommu,msi}-cells in maps"):
iommu-map has 1-cell entries targeting 2-cell #iommu-cells, treating as 1-cell output
So fix the entries to match the provider's '#iommu-cells' property.
--- arch/arm64/boot/dts/qcom/sm8150.dtsi | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
arch/arm64/boot/dts/qcom/sm8150.dtsi +4 -4
@@ -1865,8 +1865,8 @@ pcie0: pci@1c00000 { "slave_q2a", "tbu"; - iommu-map = <0x0 &apps_smmu 0x1d80 0x1>, - <0x100 &apps_smmu 0x1d81 0x1>; + iommu-map = <0x0 &apps_smmu 0x1d80 0x0 0x1>, + <0x100 &apps_smmu 0x1d81 0x0 0x1>; resets = <&gcc GCC_PCIE_0_BCR>; reset-names = "pci";
@@ -1967,8 +1967,8 @@ pcie1: pci@1c08000 { assigned-clocks = <&gcc GCC_PCIE_1_AUX_CLK>; assigned-clock-rates = <19200000>; - iommu-map = <0x0 &apps_smmu 0x1e00 0x1>, - <0x100 &apps_smmu 0x1e01 0x1>; + iommu-map = <0x0 &apps_smmu 0x1e00 0x0 0x1>, + <0x100 &apps_smmu 0x1e01 0x0 0x1>; resets = <&gcc GCC_PCIE_1_BCR>; reset-names = "pci";
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 949/1424 arm64: dts: qcom: sm8250: Fix the PCIe iommu-map entries
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Manivannan Sadhasivam <[email protected]>
[ Upstream commit c41749e9554d4e03e7074f5d1e46140bc4ac77bd ]
The IOMMU provider apps_smmu uses '#iommu-cells = <2>', but the PCIe iommu-map entries specify only one cell for the SID, omitting the SID mask. This went unnoticed until the OF core started warning with commit ccb2fd725d41 ("of: Respect #{iommu,msi}-cells in maps"):
iommu-map has 1-cell entries targeting 2-cell #iommu-cells, treating as 1-cell output
So fix the entries to match the provider's '#iommu-cells' property.
--- arch/arm64/boot/dts/qcom/sm8250.dtsi | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
arch/arm64/boot/dts/qcom/sm8250.dtsi +6 -6
@@ -1895,8 +1895,8 @@ pcie0: pci@1c00000 { "tbu", "ddrss_sf_tbu"; - iommu-map = <0x0 &apps_smmu 0x1c00 0x1>, - <0x100 &apps_smmu 0x1c01 0x1>; + iommu-map = <0x0 &apps_smmu 0x1c00 0x0 0x1>, + <0x100 &apps_smmu 0x1c01 0x0 0x1>; resets = <&gcc GCC_PCIE_0_BCR>; reset-names = "pci";
@@ -2002,8 +2002,8 @@ pcie1: pci@1c08000 { assigned-clocks = <&gcc GCC_PCIE_1_AUX_CLK>; assigned-clock-rates = <19200000>; - iommu-map = <0x0 &apps_smmu 0x1c80 0x1>, - <0x100 &apps_smmu 0x1c81 0x1>; + iommu-map = <0x0 &apps_smmu 0x1c80 0x0 0x1>, + <0x100 &apps_smmu 0x1c81 0x0 0x1>; resets = <&gcc GCC_PCIE_1_BCR>; reset-names = "pci";
@@ -2111,8 +2111,8 @@ pcie2: pci@1c10000 { assigned-clocks = <&gcc GCC_PCIE_2_AUX_CLK>; assigned-clock-rates = <19200000>; - iommu-map = <0x0 &apps_smmu 0x1d00 0x1>, - <0x100 &apps_smmu 0x1d01 0x1>; + iommu-map = <0x0 &apps_smmu 0x1d00 0x0 0x1>, + <0x100 &apps_smmu 0x1d01 0x0 0x1>; resets = <&gcc GCC_PCIE_2_BCR>; reset-names = "pci";
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 950/1424 arm64: dts: qcom: sm8350: Fix the PCIe iommu-map entries
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Manivannan Sadhasivam <[email protected]>
[ Upstream commit 80337ea3a154230621c0b4e3c831f5d81712ba18 ]
The IOMMU provider apps_smmu uses '#iommu-cells = <2>', but the PCIe iommu-map entries specify only one cell for the SID, omitting the SID mask. This went unnoticed until the OF core started warning with commit ccb2fd725d41 ("of: Respect #{iommu,msi}-cells in maps"):
iommu-map has 1-cell entries targeting 2-cell #iommu-cells, treating as 1-cell output
So fix the entries to match the provider's '#iommu-cells' property.
--- arch/arm64/boot/dts/qcom/sm8350.dtsi | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
arch/arm64/boot/dts/qcom/sm8350.dtsi +4 -4
@@ -1552,8 +1552,8 @@ pcie0: pci@1c00000 { "aggre1", "aggre0"; - iommu-map = <0x0 &apps_smmu 0x1c00 0x1>, - <0x100 &apps_smmu 0x1c01 0x1>; + iommu-map = <0x0 &apps_smmu 0x1c00 0x0 0x1>, + <0x100 &apps_smmu 0x1c01 0x0 0x1>; resets = <&gcc GCC_PCIE_0_BCR>; reset-names = "pci";
@@ -1635,8 +1635,8 @@ pcie1: pci@1c08000 { "ddrss_sf_tbu", "aggre1"; - iommu-map = <0x0 &apps_smmu 0x1c80 0x1>, - <0x100 &apps_smmu 0x1c81 0x1>; + iommu-map = <0x0 &apps_smmu 0x1c80 0x0 0x1>, + <0x100 &apps_smmu 0x1c81 0x0 0x1>; resets = <&gcc GCC_PCIE_1_BCR>; reset-names = "pci";
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 951/1424 arm64: dts: qcom: sm8450: Fix the PCIe iommu-map entries
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Manivannan Sadhasivam <[email protected]>
[ Upstream commit 9b10e56647fa8f7ab62c7e45ebf4b168f7befa7f ]
The IOMMU provider apps_smmu uses '#iommu-cells = <2>', but the PCIe iommu-map entries specify only one cell for the SID, omitting the SID mask. This went unnoticed until the OF core started warning with commit ccb2fd725d41 ("of: Respect #{iommu,msi}-cells in maps"):
iommu-map has 1-cell entries targeting 2-cell #iommu-cells, treating as 1-cell output
So fix the entries to match the provider's '#iommu-cells' property.
--- arch/arm64/boot/dts/qcom/sm8450.dtsi | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
arch/arm64/boot/dts/qcom/sm8450.dtsi +4 -4
@@ -1811,8 +1811,8 @@ pcie0: pci@1c00000 { "aggre0", "aggre1"; - iommu-map = <0x0 &apps_smmu 0x1c00 0x1>, - <0x100 &apps_smmu 0x1c01 0x1>; + iommu-map = <0x0 &apps_smmu 0x1c00 0x0 0x1>, + <0x100 &apps_smmu 0x1c01 0x0 0x1>; resets = <&gcc GCC_PCIE_0_BCR>; reset-names = "pci";
@@ -1919,8 +1919,8 @@ pcie1: pci@1c08000 { "ddrss_sf_tbu", "aggre1"; - iommu-map = <0x0 &apps_smmu 0x1c80 0x1>, - <0x100 &apps_smmu 0x1c81 0x1>; + iommu-map = <0x0 &apps_smmu 0x1c80 0x0 0x1>, + <0x100 &apps_smmu 0x1c81 0x0 0x1>; resets = <&gcc GCC_PCIE_1_BCR>; reset-names = "pci";
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 952/1424 arm64: dts: qcom: sm8550: Use GIC-ITS for PCIe0 and PCIe1
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Neil Armstrong <[email protected]>
[ Upstream commit 114990ce3edfd059648889f978cbdc83447b305b ]
Both PCIe0 and PCIe1 controllers are capable of signalling the MSIs received from endpoint devices to the CPU using GIC-ITS MSI controller. Add support for it.
The GIC-ITS MSI implementation provides an advantage over internal MSI implementation using Locality-specific Peripheral Interrupts (LPI) that would allow MSIs to be targeted for each CPU core.
Like SM8450, the IDs are swapped, but works fine on PCIe0 and PCIe1.
WiFi PCIe Device on SM8550-QRD using GIC-ITS:
218: 0 4 0 0 0 0 0 0 ITS-MSI 524288 Edge bhi 219: 0 0 5 0 0 0 0 0 ITS-MSI 524289 Edge mhi 220: 0 0 0 33 0 0 0 0 ITS-MSI 524290 Edge mhi 221: 0 0 0 0 3 0 0 0 ITS-MSI 524291 Edge ce0 222: 0 0 0 0 0 1 0 0 ITS-MSI 524292 Edge ce1 223: 0 0 0 0 0 0 38 0 ITS-MSI 524293 Edge ce2 224: 0 0 0 0 0 0 0 31 ITS-MSI 524294 Edge ce3 225: 0 0 0 0 0 0 0 0 ITS-MSI 524295 Edge ce5 226: 0 0 0 0 0 0 0 0 ITS-MSI 524296 Edge DP_EXT_IRQ 227: 0 0 0 0 0 0 0 0 ITS-MSI 524297 Edge DP_EXT_IRQ 228: 0 0 0 0 0 0 0 0 ITS-MSI 524298 Edge DP_EXT_IRQ 229: 0 0 0 0 0 0 0 0 ITS-MSI 524299 Edge DP_EXT_IRQ 230: 0 0 0 0 0 0 0 0 ITS-MSI 524300 Edge DP_EXT_IRQ 231: 0 0 0 0 0 0 0 0 ITS-MSI 524301 Edge DP_EXT_IRQ 232: 0 0 0 0 0 0 0 0 ITS-MSI 524302 Edge DP_EXT_IRQ
NVMe in SM8550-HDK M.2 Slot using GIC-ITS:
212: 0 0 22 0 0 0 0 0 ITS-MSI 134742016 Edge nvme0q0 213: 133098 0 0 0 0 0 0 0 ITS-MSI 134742017 Edge nvme0q1 214: 0 139450 0 0 0 0 0 0 ITS-MSI 134742018 Edge nvme0q2 215: 0 0 139476 0 0 0 0 0 ITS-MSI 134742019 Edge nvme0q3 216: 0 0 0 69767 0 0 0 0 ITS-MSI 134742020 Edge nvme0q4 217: 0 0 0 0 80368 0 0 0 ITS-MSI 134742021 Edge nvme0q5 218: 0 0 0 0 0 77315 0 0 ITS-MSI 134742022 Edge nvme0q6 219: 0 0 0 0 0 0 73022 0 ITS-MSI 134742023 Edge nvme0q7 220: 0 0 0 0 0 0 0 329993 ITS-MSI 134742024 Edge nvme0q8
Stable-dep-of: 16d98ee918d6 ("arm64: dts: qcom: sm8550: Fix the PCIe iommu-map entries")
--- arch/arm64/boot/dts/qcom/sm8550.dtsi | 6 ++++++ 1 file changed, 6 insertions(+)
arch/arm64/boot/dts/qcom/sm8550.dtsi +6 -0
@@ -1734,6 +1734,9 @@ pcie0: pci@1c00000 { <&gem_noc MASTER_APPSS_PROC 0 &cnoc_main SLAVE_PCIE_0 0>; interconnect-names = "pcie-mem", "cpu-pcie"; + /* Entries are reversed due to the unusual ITS DeviceID encoding */ + msi-map = <0x0 &gic_its 0x1401 0x1>, + <0x100 &gic_its 0x1400 0x1>; iommu-map = <0x0 &apps_smmu 0x1400 0x1>, <0x100 &apps_smmu 0x1401 0x1>;
@@ -1830,6 +1833,9 @@ pcie1: pci@1c08000 { <&gem_noc MASTER_APPSS_PROC 0 &cnoc_main SLAVE_PCIE_1 0>; interconnect-names = "pcie-mem", "cpu-pcie"; + /* Entries are reversed due to the unusual ITS DeviceID encoding */ + msi-map = <0x0 &gic_its 0x1481 0x1>, + <0x100 &gic_its 0x1480 0x1>; iommu-map = <0x0 &apps_smmu 0x1480 0x1>, <0x100 &apps_smmu 0x1481 0x1>;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 953/1424 arm64: dts: qcom: sm8550: Fix the msi-map entries
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Manivannan Sadhasivam <[email protected]>
[ Upstream commit 98a953fa2f4095b9777dbf59a3ed2ac3c0bf55cb ]
While adding the GIC ITS MSI support, it was found that the msi-map entries needed to be swapped to receive MSIs from the endpoint.
But later it was identified that the swapping was needed due to a bug in the Qualcomm PCIe controller driver. And since the bug is now fixed with commit bf79e33cdd89 ("PCI: qcom: Enable BDF to SID translation properly"), let's fix the msi-map entries also to reflect the actual mapping in the hardware.
Stable-dep-of: 16d98ee918d6 ("arm64: dts: qcom: sm8550: Fix the PCIe iommu-map entries")
--- arch/arm64/boot/dts/qcom/sm8550.dtsi | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-)
arch/arm64/boot/dts/qcom/sm8550.dtsi +4 -6
@@ -1734,9 +1734,8 @@ pcie0: pci@1c00000 { <&gem_noc MASTER_APPSS_PROC 0 &cnoc_main SLAVE_PCIE_0 0>; interconnect-names = "pcie-mem", "cpu-pcie"; - /* Entries are reversed due to the unusual ITS DeviceID encoding */ - msi-map = <0x0 &gic_its 0x1401 0x1>, - <0x100 &gic_its 0x1400 0x1>; + msi-map = <0x0 &gic_its 0x1400 0x1>, + <0x100 &gic_its 0x1401 0x1>; iommu-map = <0x0 &apps_smmu 0x1400 0x1>, <0x100 &apps_smmu 0x1401 0x1>;
@@ -1833,9 +1832,8 @@ pcie1: pci@1c08000 { <&gem_noc MASTER_APPSS_PROC 0 &cnoc_main SLAVE_PCIE_1 0>; interconnect-names = "pcie-mem", "cpu-pcie"; - /* Entries are reversed due to the unusual ITS DeviceID encoding */ - msi-map = <0x0 &gic_its 0x1481 0x1>, - <0x100 &gic_its 0x1480 0x1>; + msi-map = <0x0 &gic_its 0x1480 0x1>, + <0x100 &gic_its 0x1481 0x1>; iommu-map = <0x0 &apps_smmu 0x1480 0x1>, <0x100 &apps_smmu 0x1481 0x1>;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 954/1424 arm64: dts: qcom: sm8550: Fix the PCIe iommu-map entries
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Manivannan Sadhasivam <[email protected]>
[ Upstream commit 16d98ee918d63018eaa6cc260791b71319aa4faa ]
The IOMMU provider apps_smmu uses '#iommu-cells = <2>', but the PCIe iommu-map entries specify only one cell for the SID, omitting the SID mask. This went unnoticed until the OF core started warning with commit ccb2fd725d41 ("of: Respect #{iommu,msi}-cells in maps"):
iommu-map has 1-cell entries targeting 2-cell #iommu-cells, treating as 1-cell output
So fix the entries to match the provider's '#iommu-cells' property.
--- arch/arm64/boot/dts/qcom/sm8550.dtsi | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
arch/arm64/boot/dts/qcom/sm8550.dtsi +4 -4
@@ -1736,8 +1736,8 @@ pcie0: pci@1c00000 { msi-map = <0x0 &gic_its 0x1400 0x1>, <0x100 &gic_its 0x1401 0x1>; - iommu-map = <0x0 &apps_smmu 0x1400 0x1>, - <0x100 &apps_smmu 0x1401 0x1>; + iommu-map = <0x0 &apps_smmu 0x1400 0x0 0x1>, + <0x100 &apps_smmu 0x1401 0x0 0x1>; resets = <&gcc GCC_PCIE_0_BCR>; reset-names = "pci";
@@ -1834,8 +1834,8 @@ pcie1: pci@1c08000 { msi-map = <0x0 &gic_its 0x1480 0x1>, <0x100 &gic_its 0x1481 0x1>; - iommu-map = <0x0 &apps_smmu 0x1480 0x1>, - <0x100 &apps_smmu 0x1481 0x1>; + iommu-map = <0x0 &apps_smmu 0x1480 0x0 0x1>, + <0x100 &apps_smmu 0x1481 0x0 0x1>; resets = <&gcc GCC_PCIE_1_BCR>, <&gcc GCC_PCIE_1_LINK_DOWN_BCR>;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 955/1424 power: supply: isp1704_charger: cancel work on remove
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hongyan Xu <[email protected]>
[ Upstream commit 60c5b8a9ef4dbc5d69bbc1a960fe55826cb3b643 ]
The USB notifier and initial VBUS detection can schedule isp->work. The remove path unregisters the notifier and power supply, but does not wait for queued or running work before tearing down the power supply state.
Cancel the work after unregistering the notifier. Do this before unregistering the power supply.
This issue was found by a static analysis tool.
--- drivers/power/supply/isp1704_charger.c | 1 + 1 file changed, 1 insertion(+)
drivers/power/supply/isp1704_charger.c +1 -0
@@ -482,6 +482,7 @@ static int isp1704_charger_remove(struct platform_device *pdev)struct isp1704_charger *isp =platform_get_drvdata (pdev);usb_unregister_notifier (isp->phy, &isp->nb); +cancel_work_sync (&isp->work);power_supply_unregister (isp->psy);isp1704_charger_set_power (isp,0 );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 956/1424 power: supply: sc2731_charger: Convert to platform remove callback returning void
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Uwe Kleine-König <[email protected]>
[ Upstream commit 0569d4cfa800ba303647dbf8170d1e89bdee3ed9 ]
The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Eventually after all drivers are converted, .remove_new() is renamed to .remove().
Trivially convert this driver from always returning zero in the remove callback to the void returning variant.
Stable-dep-of: dfc859bb8d33 ("power: supply: sc2731_charger: cancel work on remove")
--- drivers/power/supply/sc2731_charger.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
drivers/power/supply/sc2731_charger.c +2 -4
@@ -511,13 +511,11 @@ static int sc2731_charger_probe(struct platform_device *pdev)return 0 ; } -static int sc2731_charger_remove (struct platform_device *pdev) +static void sc2731_charger_remove (struct platform_device *pdev) {struct sc2731_charger_info *info =platform_get_drvdata (pdev);usb_unregister_notifier (info->usb_phy, &info->usb_notify); - -return 0 ; }static const struct of_device_id sc2731_charger_of_match[] = {
@@ -532,7 +530,7 @@ static struct platform_driver sc2731_charger_driver = { .of_match_table = sc2731_charger_of_match, }, .probe = sc2731_charger_probe, - .remove = sc2731_charger_remove, + .remove_new = sc2731_charger_remove, };module_platform_driver (sc2731_charger_driver);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 957/1424 power: supply: sc2731_charger: cancel work on remove
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hongyan Xu <[email protected]>
[ Upstream commit dfc859bb8d332c525872f1a44028137724fa1998 ]
The USB notifier and initial charger detection can schedule info->work. The remove path unregisters the notifier, but does not cancel queued or running work before the devm-allocated driver data is released.
Set the platform drvdata used by remove, then cancel the work after unregistering the notifier.
This issue was found by a static analysis tool.
--- drivers/power/supply/sc2731_charger.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/power/supply/sc2731_charger.c +2 -0
@@ -466,6 +466,7 @@ static int sc2731_charger_probe(struct platform_device *pdev)mutex_init (&info->lock); info->dev = &pdev->dev;INIT_WORK (&info->work, sc2731_charger_work); +platform_set_drvdata (pdev, info); info->regmap =dev_get_regmap (pdev->dev.parent,NULL );if (!info->regmap) {
@@ -516,6 +517,7 @@ static void sc2731_charger_remove(struct platform_device *pdev)struct sc2731_charger_info *info =platform_get_drvdata (pdev);usb_unregister_notifier (info->usb_phy, &info->usb_notify); +cancel_work_sync (&info->work); }static const struct of_device_id sc2731_charger_of_match[] = {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 958/1424 bpf: Fix potential UAF in bpf_netns_link_update_prog
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pu Lehui <[email protected]>
[ Upstream commit 5c5997836381010fc5907b36bc17d3b19407e933 ]
In bpf_netns_link_update_prog, the checks for old_prog and prog type are currently performed locklessly before acquiring netns_bpf_mutex. This creates a race condition that can lead to a UAF issue.
If two threads concurrently execute BPF_LINK_UPDATE on the same netns link, the following execution path can trigger a UAF:
CPU0 CPU1bpf_netns_link_update_prog
if (old_prog && old_prog != link->prog)
return -EPERM;
bpf_netns_link_update_prog
if (old_prog && old_prog != link->prog)
...
old_prog = xchg(&link->prog, new_prog);
bpf_prog_put(old_prog); if (new_prog->type != link->prog->type) <-- trigger UAF
Fix this by moving the old_prog and prog->type checks inside the netns_bpf_mutex critical section. Meanwhile, use guard() to simplify lock management and avoid all the goto jumping.
--- kernel/bpf/net_namespace.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-)
kernel/bpf/net_namespace.c +6 -11
@@ -172,33 +172,28 @@ static int bpf_netns_link_update_prog(struct bpf_link *link,struct net *net;int idx, ret; +guard (mutex)(&netns_bpf_mutex); +if (old_prog && old_prog != link->prog)return -EPERM ;if (new_prog->type != link->prog->type)return -EINVAL ; -mutex_lock (&netns_bpf_mutex); - net = net_link->net; -if (!net || !check_net (net)) { +if (!net || !check_net (net))/* Link auto-detached or netns dying */ - ret = -ENOLINK ; - goto out_unlock; - } +return -ENOLINK ; run_array =rcu_dereference_protected (net->bpf.run_array[type],lockdep_is_held (&netns_bpf_mutex)); idx =link_index (net, type, net_link); ret =bpf_prog_array_update_at (run_array, idx, new_prog);if (ret) - goto out_unlock; +return ret; old_prog =xchg (&link->prog, new_prog);bpf_prog_put (old_prog); - -out_unlock: -mutex_unlock (&netns_bpf_mutex); -return ret; +return 0 ; } static int bpf_netns_link_fill_info(const struct bpf_link *link,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 959/1424 bpf: Fix potential UAF when reading bpf link info
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pu Lehui <[email protected]>
[ Upstream commit 863f3ddd0b8ac65abfb50d3be0869268ac0e277b ]
In bpf_link_show_fdinfo and bpf_link_get_info_by_fd, link->prog is accessed without holding any locks. If the prog is concurrently replaced via bpf_link_update, the old prog can be freed, leading to a potential UAF issue.
Fix this by accessing link->prog under RCU protection to safely fetch the pointer and guarantee its lifetime while reading its fields.
--- kernel/bpf/syscall.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-)
kernel/bpf/syscall.c +17 -4
@@ -2984,9 +2984,10 @@ static const char *bpf_link_type_strs[] = {static void bpf_link_show_fdinfo (struct seq_file *m,struct file *filp) {const struct bpf_link *link = filp->private_data; -const struct bpf_prog *prog = link->prog; +const struct bpf_prog *prog;enum bpf_link_type type = link->type;char prog_tag[sizeof (prog->tag) *2 +1 ] = { }; +u32 prog_id =0 ;if (type <ARRAY_SIZE (bpf_link_type_strs) && bpf_link_type_strs[type]) {seq_printf (m,"link_type:\t%s\n" , bpf_link_type_strs[type]);
@@ -2996,13 +2997,20 @@ static void bpf_link_show_fdinfo(struct seq_file *m, struct file *filp) }seq_printf (m,"link_id:\t%u\n" , link->id); +rcu_read_lock (); + prog =READ_ONCE (link->prog);if (prog) {bin2hex (prog_tag, prog->tag,sizeof (prog->tag)); + prog_id = prog->aux->id; + } +rcu_read_unlock (); + +if (prog) {seq_printf (m,"prog_tag:\t%s\n" "prog_id:\t%u\n" , prog_tag, - prog->aux->id); + prog_id); }if (link->ops->show_fdinfo) link->ops->show_fdinfo (link, m);
@@ -4750,6 +4758,7 @@ static int bpf_link_get_info_by_fd(struct file *file, {struct bpf_link_info __user *uinfo =u64_to_user_ptr (attr->info.info);struct bpf_link_info info; +const struct bpf_prog *prog;u32 info_len = attr->info.info_len;int err;
@@ -4764,8 +4773,12 @@ static int bpf_link_get_info_by_fd(struct file *file, info.type = link->type; info.id = link->id; -if (link->prog) - info.prog_id = link->prog->aux->id; + +rcu_read_lock (); + prog =READ_ONCE (link->prog); +if (prog) + info.prog_id = prog->aux->id; +rcu_read_unlock ();if (link->ops->fill_link_info) { err = link->ops->fill_link_info (link, &info);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 960/1424 lib/test_hmm: fail dmirror_fault() when the mirrored mm is gone
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Stanislav Kinsburskii <[email protected]>
[ Upstream commit 6a8024511ddf4877435c34fb3d6028aa8e590649 ]
dmirror_fault() is called from the dmirror_read() and dmirror_write() retry loops after dmirror_do_read() or dmirror_do_write() finds a missing device page table entry.
If the mirrored mm has already exited, mmget_not_zero() fails. The current code returns 0 in that case, which tells the caller that faulting succeeded even though no page was faulted and no device page table entry was installed. The caller then retries the same address, hits -ENOENT again, and can loop forever without making progress.
Return -EFAULT instead, so the ioctl fails when the mirrored mm is no longer faultable.
--- lib/test_hmm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
lib/test_hmm.c +1 -1
@@ -391,7 +391,7 @@ static int dmirror_fault(struct dmirror *dmirror, unsigned long start,/* Since the mm is for the mirrored process, get a reference first. */ if (!mmget_not_zero (mm)) -return 0 ; +return -EFAULT ;for (addr = start; addr < end; addr = range.end) { range.start = addr;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 961/1424 clk: qcom: Return expected ENOMEM error on dynamic allocation failure
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vladimir Zapolskiy <[email protected]>
[ Upstream commit 22d9257f08913b6eec3e8ece4d13d9c41f14428b ]
If a dynamic memory allocation fails, the returned error code in clock controller driver probe functions on a few legacy platforms should be set to -ENOMEM instead of -EINVAL.
--- drivers/clk/qcom/common.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/clk/qcom/common.c +2 -2
@@ -146,7 +146,7 @@ static int _qcom_cc_register_board_clk(struct device *dev, const char *path,if (!node) { fixed =devm_kzalloc (dev,sizeof (*fixed),GFP_KERNEL );if (!fixed) -return -EINVAL ; +return -ENOMEM ; fixed->fixed_rate = rate; fixed->hw.init = &init_data;
@@ -163,7 +163,7 @@ static int _qcom_cc_register_board_clk(struct device *dev, const char *path,if (add_factor) { factor =devm_kzalloc (dev,sizeof (*factor),GFP_KERNEL );if (!factor) -return -EINVAL ; +return -ENOMEM ; factor->mult = factor->div =1 ; factor->hw.init = &init_data;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 962/1424 iommu/dma: Check atomic pool allocation result directly
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aneesh Kumar K.V (Arm) <[email protected]>
[ Upstream commit af95a0ebc0a0db0762be75f51eadf770bad01aaa ]
The non-blocking, non-coherent allocation path uses dma_alloc_from_pool(), which returns the allocated page and fills cpu_addr only on success.
Do not rely on cpu_addr to detect allocation failure in this path. Check the returned page directly before using it for the IOMMU mapping.
--- drivers/iommu/dma-iommu.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-)
drivers/iommu/dma-iommu.c +8 -5
@@ -1514,13 +1514,16 @@ static void *iommu_dma_alloc(struct device *dev, size_t size, }if (IS_ENABLED (CONFIG_DMA_DIRECT_REMAP ) && - !gfpflags_allow_blocking (gfp) && !coherent) + !gfpflags_allow_blocking (gfp) && !coherent) { page =dma_alloc_from_pool (dev,PAGE_ALIGN (size), &cpu_addr, - gfp,NULL ); -else + gfp,NULL ); +if (!page) +return NULL ; + }else { cpu_addr =iommu_dma_alloc_pages (dev, size, &page, gfp, attrs); -if (!cpu_addr) -return NULL ; +if (!cpu_addr) +return NULL ; + } *handle =__iommu_dma_map (dev,page_to_phys (page), size, ioprot, dev->coherent_dma_mask);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 963/1424 swiotlb: Preserve allocation virtual address for dynamic pools
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aneesh Kumar K.V (Arm) <[email protected]>
[ Upstream commit 57d29044d0f29a76c6ec0c112c8c7371d5608dc7 ]
swiotlb_alloc_tlb() can allocate from the DMA atomic pool when a decrypted pool is needed from atomic context. With CONFIG_DMA_DIRECT_REMAP, the atomic pool is backed by remapped virtual addresses, which are not the same as the direct-map addresses returned by phys_to_virt().
swiotlb_init_io_tlb_pool() currently reconstructs the pool virtual address from the physical start address. For atomic-pool backed allocations this stores the wrong address in pool->vaddr. Later, swiotlb_free_tlb() passes that address to dma_free_from_pool(), which will fail to recognize the chunk
Pass the virtual address returned by the allocation path into swiotlb_init_io_tlb_pool(), and store that address in pool->vaddr. This keeps the pool free path using the same virtual address as the allocator.
--- kernel/dma/swiotlb.c | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-)
kernel/dma/swiotlb.c +19 -12
@@ -268,9 +268,9 @@ void __init swiotlb_update_mem_attributes(void) }static void swiotlb_init_io_tlb_pool (struct io_tlb_pool *mem,phys_addr_t start, -unsigned long nslabs,bool late_alloc,unsigned int nareas) +void *vaddr,unsigned long nslabs,bool late_alloc, +unsigned int nareas) { -void *vaddr =phys_to_virt (start);unsigned long bytes = nslabs <<IO_TLB_SHIFT , i; mem->nslabs = nslabs;
@@ -411,7 +411,7 @@ void __init swiotlb_init_remap(bool addressing_limit, unsigned int flags,return ; } -swiotlb_init_io_tlb_pool (mem,__pa (tlb), nslabs, false, nareas); +swiotlb_init_io_tlb_pool (mem,__pa (tlb), tlb, nslabs, false, nareas);add_mem_pool (&io_tlb_default_mem, mem);if (flags &SWIOTLB_VERBOSE )
@@ -509,7 +509,7 @@ int swiotlb_init_late(size_t size, gfp_t gfp_mask,set_memory_decrypted ((unsigned long )vstart, (nslabs <<IO_TLB_SHIFT ) >>PAGE_SHIFT ); -swiotlb_init_io_tlb_pool (mem,virt_to_phys (vstart), nslabs, true, +swiotlb_init_io_tlb_pool (mem,virt_to_phys (vstart), vstart, nslabs, true, nareas);add_mem_pool (&io_tlb_default_mem, mem);
@@ -607,25 +607,26 @@ static struct page *alloc_dma_pages(gfp_t gfp, size_t bytes, u64 phys_limit)* @bytes: Size of the buffer. * @phys_limit: Maximum allowed physical address of the buffer. * @gfp: GFP flags for the allocation. +* @vaddr: Receives the virtual address for the allocated buffer. * * Return: Allocated pages, or %NULL on allocation failure. */ static struct page *swiotlb_alloc_tlb (struct device *dev,size_t bytes, -u64 phys_limit,gfp_t gfp) +u64 phys_limit,gfp_t gfp,void **vaddr) {struct page *page; + *vaddr =NULL ; +/* * Allocate from the atomic pools if memory is encrypted and * the allocation is atomic, because decrypting may block. */ if (!gfpflags_allow_blocking (gfp) && dev &&force_dma_unencrypted (dev)) { -void *vaddr; -if (!IS_ENABLED (CONFIG_DMA_COHERENT_POOL ))return NULL ; -return dma_alloc_from_pool (dev, bytes, &vaddr, gfp, +return dma_alloc_from_pool (dev, bytes, vaddr, gfp, dma_coherent_ok); }
@@ -647,6 +648,8 @@ static struct page *swiotlb_alloc_tlb(struct device *dev, size_t bytes,return NULL ; } +if (page) + *vaddr =phys_to_virt (page_to_phys (page));return page; }
@@ -687,6 +690,7 @@ static struct io_tlb_pool *swiotlb_alloc_pool(struct device *dev, {struct io_tlb_pool *pool;unsigned int slot_order; +void *tlb_vaddr;struct page *tlb;size_t pool_size;size_t tlb_size;
@@ -703,7 +707,8 @@ static struct io_tlb_pool *swiotlb_alloc_pool(struct device *dev, pool->areas = (void *)pool +sizeof (*pool); tlb_size = nslabs <<IO_TLB_SHIFT ; -while (!(tlb =swiotlb_alloc_tlb (dev, tlb_size, phys_limit, gfp))) { +while (!(tlb =swiotlb_alloc_tlb (dev, tlb_size, phys_limit, gfp, + &tlb_vaddr))) {if (nslabs <= minslabs) goto error_tlb; nslabs =ALIGN (nslabs >>1 ,IO_TLB_SEGSIZE );
@@ -717,11 +722,12 @@ static struct io_tlb_pool *swiotlb_alloc_pool(struct device *dev,if (!pool->slots) goto error_slots; -swiotlb_init_io_tlb_pool (pool,page_to_phys (tlb), nslabs, true, nareas); +swiotlb_init_io_tlb_pool (pool,page_to_phys (tlb), tlb_vaddr, nslabs, + true, nareas);return pool; error_slots: -swiotlb_free_tlb (page_address (tlb), tlb_size); +swiotlb_free_tlb (tlb_vaddr, tlb_size); error_tlb:kfree (pool); error:
@@ -1746,7 +1752,8 @@ static int rmem_swiotlb_device_init(struct reserved_mem *rmem,set_memory_decrypted ((unsigned long )phys_to_virt (rmem->base), rmem->size >>PAGE_SHIFT ); -swiotlb_init_io_tlb_pool (pool, rmem->base, nslabs, +swiotlb_init_io_tlb_pool (pool, rmem->base,phys_to_virt (rmem->base), + nslabs, false, nareas); mem->force_bounce = true; mem->for_alloc = true;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 964/1424 i3c: dw: avoid shift-out-of-bounds when DAA assigns no devices
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jakub Kicinski <[email protected]>
[ Upstream commit 038cf48b3170af26a70bf2dee4f8c3ac910f5176 ]
On an empty bus ENTDAA assigns nothing, so cmd->rx_len (the count of addresses left unassigned) equals master->maxdevs.
The GENMASK() index master->maxdevs - cmd->rx_len - 1 then becomes -1, which trips up UBSAN. This happens every time on boot on a Gigabyte/AMD server:
UBSAN: shift-out-of-bounds in drivers/i3c/master/dw-i3c-master.c:905:12
shift exponent 64 is too large for 64-bit type 'long unsigned int'
CPU: 7 UID: 0 PID: 963 Comm: (udev-worker) Not tainted 7.0.11-200.fc44.x86_64 #1 PREEMPT(lazy)
Hardware name: Giga Computing E163-Z34-AAH1-000/MZ33-DC1-000, BIOS R32_F45 04/01/2026
Call Trace:
<TASK>
dump_stack_lvl+0x5d/0x80
ubsan_epilogue+0x5/0x2b
__ubsan_handle_shift_out_of_bounds.cold+0xd7/0x1ab
dw_i3c_master_daa.cold+0x1b/0x96 [dw_i3c_master]
i3c_master_do_daa_ext.part.0+0x3e/0xf0 [i3c]Skip the mask when no new device was assigned.
--- drivers/i3c/master/dw-i3c-master.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-)
drivers/i3c/master/dw-i3c-master.c +9 -1
@@ -829,7 +829,15 @@ static int dw_i3c_master_daa(struct i3c_master_controller *m)if (!wait_for_completion_timeout (&xfer->comp,XFER_TIMEOUT ))dw_i3c_master_dequeue_xfer (master, xfer); - newdevs =GENMASK (master->maxdevs - cmd->rx_len -1 ,0 ); +/* +* cmd->rx_len holds the number of addresses ENTDAA left unassigned. +* On an empty bus rx_len == maxdevs, so avoid GENMASK(-1, 0). +*/ +if (cmd->rx_len >= master->maxdevs) + newdevs =0 ; +else + newdevs =GENMASK (master->maxdevs - cmd->rx_len -1 ,0 ); + newdevs &= ~olddevs;for (pos =0 ; pos < master->maxdevs; pos++) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 965/1424 i3c: master: Fix device_register() error path
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Adrian Hunter <[email protected]>
[ Upstream commit 74be657d98a8d684c0475f3cbd450ef2a30ffc73 ]
When device_register() fails in i3c_master_register_new_i3c_devs(), put_device() is called to drop the reference taken by device_register(). That drops the last reference, so the device's release callback i3c_device_release() runs and frees the i3c_device.
Two problems follow from that:
i3c_device_release() does WARN_ON(i3cdev->desc), so it warns because desc->dev->desc still points back at the descriptor. Clear it before calling put_device().
After put_device() frees the i3c_device, desc->dev is left pointing at freed memory, so clear desc->dev as well. That prevents, for example, i3c_master_unregister_i3c_devs() seeing desc->dev as non-NULL and dereferencing it.
--- drivers/i3c/master.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/i3c/master.c +2 -0
@@ -1648,7 +1648,9 @@ i3c_master_register_new_i3c_devs(struct i3c_master_controller *master)if (ret) {dev_err (&master->dev,"Failed to add I3C device (err = %d)\n" , ret); + desc->dev->desc =NULL ;put_device (&desc->dev->dev); + desc->dev =NULL ; } } }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 966/1424 locking/lockdep: Fix NULL pointer dereference in __lock_set_class()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Naveen Kumar Chaudhary <[email protected]>
[ Upstream commit 7577e00b9ab506202b9f1a33de3cc8cc6413a4db ]
register_lock_class() can return NULL when the lock class pool is exhausted, graph_lock() fails, or key validation fails. However, __lock_set_class() uses the return value directly in pointer arithmetic without a NULL check:
class = register_lock_class(lock, subclass, 0); hlock->class_idx = class - lock_classes;
If class is NULL, this computes a wild offset that corrupts hlock->class_idx. The subsequent reacquire_held_locks() call will invoke hlock_class() with this corrupted index, leading to a NULL or out-of-bounds pointer dereference.
Add the missing NULL check, consistent with how __lock_acquire() already handles this case at the same call site.
--- kernel/locking/lockdep.c | 2 ++ 1 file changed, 2 insertions(+)
kernel/locking/lockdep.c +2 -0
@@ -5331,6 +5331,8 @@ __lock_set_class(struct lockdep_map *lock, const char *name, lock->wait_type_outer, lock->lock_type); class =register_lock_class (lock, subclass,0 ); +if (!class) +return 0 ; hlock->class_idx = class - lock_classes; curr->lockdep_depth = i;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 967/1424 misc: vmc_vmci: Fix potential memory leak in vmci_event_subscribe()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Abdun Nihaal <[email protected]>
[ Upstream commit 210854a96ef18b09b45a2a59ff14ca06dfe5ad4d ]
The memory allocated for struct vmci_subscription (sub) is not freed in the error path when have_new_id is false. Fix that by adding a kfree() call, and moving the read of sub->id to a point before freeing.
--- drivers/misc/vmw_vmci/vmci_event.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/misc/vmw_vmci/vmci_event.c +2 -2
@@ -179,16 +179,16 @@ int vmci_event_subscribe(u32 event, } } + *new_subscription_id = sub->id;if (have_new_id) {list_add_rcu (&sub->node, &subscriber_array[event]); retval =VMCI_SUCCESS ; }else { +kfree (sub); retval =VMCI_ERROR_NO_RESOURCES ; }mutex_unlock (&subscriber_mutex); - - *new_subscription_id = sub->id;return retval; }EXPORT_SYMBOL_GPL (vmci_event_subscribe);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 968/1424 fanotify: report full event length for FIONREAD
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yichong Chen <[email protected]>
[ Upstream commit 68615158c12de36220446dfea5cfdf9ba6c19690 ]
fanotify_ioctl(FIONREAD) reports the number of bytes available to read from the event queue. It currently accounts only FAN_EVENT_METADATA_LEN for each queued event.
That underestimates events that carry additional information records, such as FAN_REPORT_DFID_NAME events. A userspace program that uses FIONREAD to size its read buffer can receive a length that is smaller than the next event. Reading with that buffer then fails with -EINVAL, while a larger buffer succeeds and reports a larger metadata.event_len.
Use fanotify_event_len() when summing queued events so FIONREAD includes all info records.
--- fs/notify/fanotify/fanotify_user.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
fs/notify/fanotify/fanotify_user.c +4 -1
@@ -972,11 +972,13 @@ static long fanotify_ioctl(struct file *file, unsigned int cmd, unsigned long ar {struct fsnotify_group *group;struct fsnotify_event *fsn_event; +unsigned int info_mode;void __user *p;int ret = -ENOTTY ;size_t send_len =0 ; group = file->private_data; + info_mode =FAN_GROUP_FLAG (group,FANOTIFY_INFO_MODES ); p = (void __user *) arg;
@@ -984,7 +986,8 @@ static long fanotify_ioctl(struct file *file, unsigned int cmd, unsigned long arcase FIONREAD :spin_lock (&group->notification_lock);list_for_each_entry (fsn_event, &group->notification_list, list) - send_len +=FAN_EVENT_METADATA_LEN ; + send_len +=fanotify_event_len (info_mode, +FANOTIFY_E (fsn_event));spin_unlock (&group->notification_lock); ret =put_user (send_len, (int __user *) p);break ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 969/1424 wifi: mt76: mt76x02: do not WARN on invalid rx descriptor length
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Devin Wittmayer <[email protected]>
[ Upstream commit 81497634d9f872fd3e8b03aada55574afff6f174 ]
The MPDU length in the rx descriptor comes from the hardware. In monitor mode with the fcsfail filter enabled, the hardware passes up corrupted frames, and a corrupted frame can report a length larger than the received buffer. The bounds check correctly discards such frames, but its WARN_ON_ONCE wrapper means any over-the-air garbage frame taints the kernel, and panics it on the first such frame when panic_on_warn is set.
Drop the WARN and discard the frame silently, matching what commit c2d4c8723dbf ("mt76x2: remove some harmless WARN_ONs in tx status and rx path") did for the neighboring rx and tx status paths.
Observed immediately on rx with an MT7612U in fcsfail monitor mode on a busy channel.
--- drivers/net/wireless/mediatek/mt76/mt76x02_mac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/wireless/mediatek/mt76/mt76x02_mac.c +1 -1
@@ -850,7 +850,7 @@ int mt76x02_mac_process_rx(struct mt76x02_dev *dev, struct sk_buff *skb, } } -if (WARN_ON_ONCE (len > skb->len)) +if (len > skb->len)return -EINVAL ;if (pskb_trim (skb, len))
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 970/1424 wifi: mt76: mt7921: validate CLC firmware records
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Laxman Acharya Padhya <[email protected]>
[ Upstream commit 9417c5818a0146980c2608fda94c908e604eb033 ]
The CLC region is supplied by firmware, but the loader trusts the region count and each record length. A malformed image can make the region table pointer precede the firmware buffer, make the record loop fail to advance, or index phy->clc past its end. Validate the table and record bounds before dereferencing or copying.
--- .../net/wireless/mediatek/mt76/mt7921/mcu.c | 28 ++++++++++++++++--- 1 file changed, 24 insertions(+), 4 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7921/mcu.c +24 -4
@@ -372,7 +372,8 @@ static int mt7921_load_clc(struct mt792x_dev *dev, const char *fw_name)struct mt76_dev *mdev = &dev->mt76;struct mt792x_phy *phy = &dev->phy;const struct firmware *fw; -int ret, i, len, offset =0 ; +size_t clc_len, fw_data_len, len, offset =0 ; +int ret, i;u8 *clc_base =NULL , hw_encap =0 ; if (mt7921_disable_clc ||
@@ -397,13 +398,21 @@ static int mt7921_load_clc(struct mt792x_dev *dev, const char *fw_name) } hdr = (const void *)(fw->data + fw->size -sizeof (*hdr)); +if (hdr->n_region > (fw->size -sizeof (*hdr)) /sizeof (*region)) { +dev_err (mdev->dev,"Invalid firmware region table\n" ); + ret = -EINVAL ; + goto out; + } + fw_data_len = fw->size -sizeof (*hdr) - + hdr->n_region *sizeof (*region); +for (i =0 ; i < hdr->n_region; i++) { region = (const void *)((const u8 *)hdr - (hdr->n_region - i) *sizeof (*region)); len =le32_to_cpu (region->len);/* check if we have valid buffer size */ -if (offset + len > fw->size) { +if (len > fw_data_len - offset) {dev_err (mdev->dev,"Invalid firmware region\n" ); ret = -EINVAL ; goto out;
@@ -420,8 +429,19 @@ static int mt7921_load_clc(struct mt792x_dev *dev, const char *fw_name)if (!clc_base) goto out; -for (offset =0 ; offset < len; offset +=le32_to_cpu (clc->len)) { +for (offset =0 ; offset < len; offset += clc_len) { +if (len - offset <sizeof (*clc)) { + ret = -EINVAL ; + goto out; + } + clc = (const struct mt7921_clc *)(clc_base + offset); + clc_len =le32_to_cpu (clc->len); +if (clc_len <sizeof (*clc) || clc_len > len - offset || + clc->idx >=ARRAY_SIZE (phy->clc)) { + ret = -EINVAL ; + goto out; + }/* do not init buf again if chip reset triggered */ if (phy->clc[clc->idx])
@@ -433,7 +453,7 @@ static int mt7921_load_clc(struct mt792x_dev *dev, const char *fw_name)continue ; phy->clc[clc->idx] =devm_kmemdup (mdev->dev, clc, -le32_to_cpu (clc->len), + clc_len,GFP_KERNEL );if (!phy->clc[clc->idx]) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 971/1424 wifi: mt76: mt7915: fix net_fill_forward_path for non-DBDC mt7986
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhi-Jun You <[email protected]>
[ Upstream commit bade0d238b60c29dafcc7da17501fa489495d6ae ]
Current implementation assumes that the hardware supports DBDC or single band and binds to band0.
This causes net_fill_forward_path to select the wrong queue for non-DBDC mt7986 because it binds to band1 and getting the following in dmesg:
ieee80211 phy2: WA: --> drop by reaseon:1, msdu id = 0xc002 but failed!mtk_wed1: error status=00000002
ieee80211 phy2: WA: txblk10324e00
len = 128
DW0 : 10 00 00 00
DW1 : 00 00 00 00
DW2 : 00 00 00 00
DW3 : 72 0f 94 68
DW4 : 00 00 00 00
DW5 : ff 03 00 00
DW6 : 00 00 3c 40
DW7 : 00 17 dd 14
DW8 : 79 6f 00 00
DW9 : 02 c0 00 00
DW10 : 58 c5 34 10
DW11 : 00 00 00 00
DW12 : 00 06 3e 00
DW13 : 00 00 00 80
DW14 : 10 8c 00 00
DW15 : 00 00 00 00
DW16 : 00 00 00 00
DW17 : 00 00 00 00
DW18 : 00 00 00 00
DW19 : 00 00 00 00
DW20 : 00 00 00 00
DW21 : 00 00 00 00
DW22 : 00 00 00 00
DW23 : 00 00 00 00
DW24 : 00 00 00 00
DW25 : 00 00 00 00
DW26 : 00 00 00 00
DW27 : 00 00 00 00
DW28 : 00 00 00 00
DW29 : 00 00 00 00
DW30 : 00 00 00 00
DW31 : 00 00 00 00
Fix it by using phy->mt76->band_idx for queue which works for both non-DBDC and DBDC devices.
--- drivers/net/wireless/mediatek/mt76/mt7915/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/wireless/mediatek/mt76/mt7915/main.c +1 -1
@@ -1643,7 +1643,7 @@ mt7915_net_fill_forward_path(struct ieee80211_hw *hw, path->mtk_wdma.wdma_idx = wed->wdma_idx; path->mtk_wdma.bss = mvif->mt76.idx; path->mtk_wdma.wcid =is_mt7915 (&dev->mt76) ? msta->wcid.idx :0x3ff ; - path->mtk_wdma.queue = phy != &dev->phy; + path->mtk_wdma.queue = phy->mt76->band_idx; ctx->dev =NULL ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 972/1424 wifi: mt76: mt792x: Fix memory leak in SDIO TX path
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eason Lai <[email protected]>
[ Upstream commit 808f2767d4217a5b96f674288573b9b89d432eed ]
When tx_prepare_skb() returns an error in the SDIO TX path, the skb is not freed, leading to a memory leak. This can occur when zero-length frames (such as WNM NULL frames) are dropped to prevent potential hardware TX hangs.
Fix this by properly releasing the skb with ieee80211_tx_status_ext() when tx_prepare_skb() fails.
--- drivers/net/wireless/mediatek/mt76/sdio.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)
drivers/net/wireless/mediatek/mt76/sdio.c +10 -1
@@ -519,6 +519,10 @@ mt76s_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q, enum mt76_txq_id qid, struct sk_buff *skb, struct mt76_wcid *wcid, struct ieee80211_sta *sta) { + struct ieee80211_tx_status status = { + .sta = sta, + }; +struct mt76_tx_info tx_info = { .skb = skb, };
@@ -530,8 +534,13 @@ mt76s_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q, skb->prev = skb->next =NULL ; err = dev->drv->tx_prepare_skb (dev,NULL , qid, wcid, sta, &tx_info); -if (err <0 ) +if (err <0 ) { + status.skb = tx_info.skb; +spin_lock_bh (&dev->rx_lock); +ieee80211_tx_status_ext (dev->hw, &status); +spin_unlock_bh (&dev->rx_lock);return err; + } q->entry[q->head].skb = tx_info.skb; q->entry[q->head].buf_sz = len;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 973/1424 wifi: mt76: mt7996: set MT76_MCU_RESET before waking MCU waiters on full reset
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Felix Fietkau <[email protected]>
[ Upstream commit 6469ae71e7e5d0132c934972f628f346ad0379cd ]
mt7996_mac_full_reset() called wake_up(&dev->mt76.mcu.wait) without first setting MT76_MCU_RESET. The MCU response wait condition only checks the response queue and that bit, so the wake-up released nobody: a thread blocked in an MCU command against the dead firmware (typically holding dev->mt76.mutex) stayed asleep until its multi-second timeout, stalling recovery. Set the bit before the wake-up, as mt7915 does.
--- drivers/net/wireless/mediatek/mt76/mt7996/mac.c | 1 + 1 file changed, 1 insertion(+)
drivers/net/wireless/mediatek/mt76/mt7996/mac.c +1 -0
@@ -1737,6 +1737,7 @@ mt7996_mac_full_reset(struct mt7996_dev *dev) phy3 =mt7996_phy3 (dev); dev->recovery.hw_full_reset = true; +set_bit (MT76_MCU_RESET , &dev->mphy.state);wake_up (&dev->mt76.mcu.wait);ieee80211_stop_queues (mt76_hw (dev));if (phy2)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 974/1424 wifi: mt76: mt7915: avoid nss underflow in mt7915_mcu_get_sta_nss
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Felix Fietkau <[email protected]>
[ Upstream commit 4a2f4be532e3ea4e2b536e411793a05aaa51af25 ]
If a peer's VHT/HE MCS map has no supported spatial stream (all fields 0x3), the loop exits with nss == 0 and the function returned (u8)-1 (255), which was then written into the firmware sta_rec_bf beamforming fields. Clamp the result to 0.
--- drivers/net/wireless/mediatek/mt76/mt7915/mcu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +1 -1
@@ -51,7 +51,7 @@ mt7915_mcu_get_sta_nss(u16 mcs_map)break ; } -return nss -1 ; +return nss ? nss -1 :0 ; } static void
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 975/1424 wifi: mt76: mt7996: dont report a zero TX bitrate
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Felix Fietkau <[email protected]>
[ Upstream commit d4d92ccded678c92c390003926097ddbb6516bc7 ]
mt7996_sta_statistics() set NL80211_STA_INFO_TX_BITRATE unconditionally after the block that already sets it, so a station with no rate info yet was reported to userspace with a valid-but-zero TX rate. Drop the redundant unconditional assignments; the in-block ones are sufficient.
--- drivers/net/wireless/mediatek/mt76/mt7996/main.c | 2 -- 1 file changed, 2 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7996/main.c +0 -2
@@ -998,8 +998,6 @@ static void mt7996_sta_statistics(struct ieee80211_hw *hw, sinfo->txrate.flags = txrate->flags; sinfo->filled |=BIT_ULL (NL80211_STA_INFO_TX_BITRATE ); } - sinfo->txrate.flags = txrate->flags; - sinfo->filled |=BIT_ULL (NL80211_STA_INFO_TX_BITRATE ); sinfo->ack_signal = (s8 )msta->ack_signal; sinfo->filled |=BIT_ULL (NL80211_STA_INFO_ACK_SIGNAL );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 976/1424 wifi: mt76: mt7915: poll the correct SLP CTRL register for the second adie
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Felix Fietkau <[email protected]>
[ Upstream commit dd59a6126a8f1bd52bf6bd057bf0c8307f76a74b ]
The clock enable path for the second adie sets MT_ADIE_SLP_CTRL_CK0(1) but polled the busy bit of MT_ADIE_SLP_CTRL_CK0(0), so dual-adie bring-up could proceed before the adie1 clock was stable.
--- drivers/net/wireless/mediatek/mt76/mt7915/soc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/wireless/mediatek/mt76/mt7915/soc.c +1 -1
@@ -913,7 +913,7 @@ static void mt7986_wmac_clock_enable(struct mt7915_dev *dev, u32 adie_type)read_poll_timeout (mt76_rr, cur, !(cur &MT_SLP_CTRL_BSY_MASK ),USEC_PER_MSEC ,50 *USEC_PER_MSEC , false, - dev,MT_ADIE_SLP_CTRL_CK0 (0 )); + dev,MT_ADIE_SLP_CTRL_CK0 (1 )); }mt76_wmac_spi_unlock (dev);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 977/1424 wifi: mt76: mt7996: bound TLV walk in mt7996_mcu_get_chip_config
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Felix Fietkau <[email protected]>
[ Upstream commit 44af52467e72094351a362bf69effd52f1d9c186 ]
The response TLV loop advanced by tlv->len without a minimum, so a theoretical firmware response containing a zero-length TLV could spin forever, hanging the CPU during device probe.
The u32 payload was also read without bounds checking. Reject a short fixed field, stop on a TLV whose length underruns the header or overruns the skb.
--- drivers/net/wireless/mediatek/mt76/mt7996/mcu.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7996/mcu.c +13 -3
@@ -3172,21 +3172,31 @@ int mt7996_mcu_get_chip_config(struct mt7996_dev *dev, u32 *cap)return ret;/* fixed field */ +if (skb->len <4 ) { +dev_kfree_skb (skb); +return -EINVAL ; + }skb_pull (skb,4 ); buf = skb->data; -while (buf - skb->data < skb->len) { +while (buf - skb->data +sizeof (struct tlv ) <= skb->len) {struct tlv *tlv = (struct tlv *)buf; +u16 tlv_len =le16_to_cpu (tlv->len); + +if (tlv_len <sizeof (*tlv) || + tlv_len > skb->len - (buf - skb->data)) +break ;switch (le16_to_cpu (tlv->tag)) {case UNI_EVENT_CHIP_CONFIG_EFUSE_VERSION : - *cap =le32_to_cpu (*(__le32 *)(buf +sizeof (*tlv))); +if (tlv_len >=sizeof (*tlv) +sizeof (__le32)) + *cap =le32_to_cpu (*(__le32 *)(buf +sizeof (*tlv)));break ;default :break ; } - buf +=le16_to_cpu (tlv->len); + buf += tlv_len; }dev_kfree_skb (skb);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 978/1424 wifi: mt76: mt7996: reserve space for the CSA-abort countdown TLV
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Felix Fietkau <[email protected]>
[ Upstream commit 50c66bab321140c49aa2ed779a3ec9d2f085b458 ]
When a CSA countdown is active, mt7996_mcu_beacon_cntdwn() emits two bss_bcn_cntdwn_tlv entries (the CSA countdown and the CCA-abort BCC), but MT7996_BEACON_UPDATE_SIZE only reserved one. With MBSSID enabled and a near-maximum beacon template the extra 8 bytes could push the offload command past MT7996_MAX_BSS_OFFLOAD_SIZE and trigger skb_over_panic(). Reserve room for both countdown TLVs.
--- drivers/net/wireless/mediatek/mt76/mt7996/mcu.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/wireless/mediatek/mt76/mt7996/mcu.h +1 -1
@@ -591,7 +591,7 @@ enum {#define MT7996_BEACON_UPDATE_SIZE (sizeof(struct bss_req_hdr) + \ sizeof(struct bss_bcn_content_tlv) + \ 4 + MT_TXD_SIZE + \ - sizeof(struct bss_bcn_cntdwn_tlv) + \ + sizeof(struct bss_bcn_cntdwn_tlv) * 2 + \ sizeof(struct bss_bcn_mbss_tlv))#define MT7996_MAX_BSS_OFFLOAD_SIZE (MT7996_MAX_BEACON_SIZE + \ MT7996_BEACON_UPDATE_SIZE)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 979/1424 wifi: mt76: mt7915: use little-endian for bss_info_ra wire fields
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Felix Fietkau <[email protected]>
[ Upstream commit 04280d0a56be4264720e7b205daaa332c715e5ec ]
train_up_high_thres, train_up_rule_rssi and low_traffic_thres were declared as host-native short in a firmware-facing TLV and assigned host-order constants, so on a big-endian host the firmware received byte-swapped rate-adaptation thresholds. Declare them __le16 and convert with cpu_to_le16().
--- drivers/net/wireless/mediatek/mt76/mt7915/mcu.c | 6 +++--- drivers/net/wireless/mediatek/mt76/mt7915/mcu.h | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +3 -3
@@ -526,9 +526,9 @@ mt7915_mcu_bss_ra_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, ra->rx_streams = max_nss; ra->algo =4 ; ra->train_up_rule =2 ; - ra->train_up_high_thres =110 ; - ra->train_up_rule_rssi =-70 ; - ra->low_traffic_thres =2 ; + ra->train_up_high_thres =cpu_to_le16 (110 ); + ra->train_up_rule_rssi =cpu_to_le16 (-70 ); + ra->low_traffic_thres =cpu_to_le16 (2 ); ra->phy_cap =cpu_to_le32 (0xfdf ); ra->interval =cpu_to_le32 (500 ); ra->fast_interval =cpu_to_le32 (100 );
drivers/net/wireless/mediatek/mt76/mt7915/mcu.h +3 -3
@@ -318,9 +318,9 @@ struct bss_info_ra {u8 antenna_idx;u8 train_up_rule;u8 rsv[3 ]; -unsigned short train_up_high_thres; -short train_up_rule_rssi; -unsigned short low_traffic_thres; +__le16 train_up_high_thres; +__le16 train_up_rule_rssi; +__le16 low_traffic_thres;__le16 max_phyrate;__le32 phy_cap;__le32 interval;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 980/1424 ACPI: processor: idle: Optimize ACPI idle driver registration
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Huisong Li <[email protected]>
[ Upstream commit 7a8c994cbb2db3c5335cee35fd486557f5aaf7e1 ]
Currently, the ACPI idle driver is registered from within a CPU hotplug callback. Although this didn't cause any functional issues, this is questionable and confusing. And it is better to register the cpuidle driver when all of the CPUs have been brought up.
So add a new function to initialize acpi_idle_driver based on the power management information of an available CPU and register cpuidle driver in acpi_processor_driver_init().
This commit has four changes under the commit 7a8c994cbb2d (ACPI:
processor: idle: Optimize ACPI idle driver registration):
1) move acpi_processor_register_idle_driver() ahead of the driver_register().
2) add acpi_processor_cstate_first_run_checks() before calling acpi_processor_get_power_info().
3) squash the commit 9d68320b2bca (ACPI: processor: idle: Fix function defined but not used warning) into this change.
4) use for_each_possible_cpu(cpu) to scan all possible cpus.
[ rjw: New comment edits, changelog tweak ]
Stable-dep-of: 06f32dd67e6b ("ACPI: processor: Unregister cpufreq notifier on init failure")
--- drivers/acpi/processor_driver.c | 10 ++++- drivers/acpi/processor_idle.c | 66 +++++++++++++++++++++------------ include/acpi/processor.h | 2 + 3 files changed, 54 insertions(+), 24 deletions(-)
drivers/acpi/processor_driver.c +9 -1
@@ -269,9 +269,11 @@ static int __init acpi_processor_driver_init(void)acpi_processor_ignore_ppc_init (); } +acpi_processor_register_idle_driver (); + result =driver_register (&acpi_processor_driver);if (result <0 ) -return result; + goto unregister_idle_drv; result = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, "acpi/cpu-drv:online",
@@ -284,8 +286,13 @@ static int __init acpi_processor_driver_init(void)acpi_processor_throttling_init ();return 0 ; + err:driver_unregister (&acpi_processor_driver); + +unregister_idle_drv: +acpi_processor_unregister_idle_driver (); +return result; }
@@ -303,6 +310,7 @@ static void __exit acpi_processor_driver_exit(void)cpuhp_remove_state_nocalls (hp_online);cpuhp_remove_state_nocalls (CPUHP_ACPI_CPUDRV_DEAD );driver_unregister (&acpi_processor_driver); +acpi_processor_unregister_idle_driver (); }module_init (acpi_processor_driver_init);
drivers/acpi/processor_idle.c +43 -23
96 lines not on this page · raw message
include/acpi/processor.h +2 -0
@@ -418,6 +418,8 @@ int acpi_processor_power_init(struct acpi_processor *pr);int acpi_processor_power_exit (struct acpi_processor *pr);int acpi_processor_power_state_has_changed (struct acpi_processor *pr);int acpi_processor_hotplug (struct acpi_processor *pr); +void acpi_processor_register_idle_driver (void ); +void acpi_processor_unregister_idle_driver (void );#else static inline int acpi_processor_power_init (struct acpi_processor *pr) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 981/1424 ACPI: processor: Unregister cpufreq notifier on init failure
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Can Peng <[email protected]>
[ Upstream commit 06f32dd67e6b23a05bef0d8183c5335af91c0c3b ]
acpi_processor_driver_init() registers the cpufreq policy notifier before registering the ACPI processor driver and setting up CPU hotplug state.
If driver_register() or cpuhp_setup_state() fails, the error path only unregisters the ACPI processor driver and the idle driver. The cpufreq notifier remains registered even though initialization failed.
Mirror the module exit path on the init failure path and unregister the cpufreq notifier when it has been registered.
--- drivers/acpi/processor_driver.c | 6 ++++++ 1 file changed, 6 insertions(+)
drivers/acpi/processor_driver.c +6 -0
@@ -293,6 +293,12 @@ static int __init acpi_processor_driver_init(void) unregister_idle_drv:acpi_processor_unregister_idle_driver (); +if (acpi_processor_cpufreq_init) { +cpufreq_unregister_notifier (&acpi_processor_notifier_block, +CPUFREQ_POLICY_NOTIFIER ); + acpi_processor_cpufreq_init = false; + } +return result; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 982/1424 perf: arm_spe: Make wakeup range check overflow safe
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Leo Yan <[email protected]>
[ Upstream commit fcc5eaea2d234162dfb8258372dd897bc2a1b862 ]
The current code checks whether the wakeup point is in the current writable range by comparing it with handle->head + handle->size.
The perf AUX head is a monotonically increasing index, so that addition can overflow when head is close to ULONG_MAX. In that case, a wakeup point which is still inside the free space range can be missed.
Use unsigned subtraction to compare the distance from head to wakeup against the handle->size. This can dismiss the issue when addition overflow.
This is unlikely to happen in practice, but the change makes the watermark check logically correct.
--- drivers/perf/arm_spe_pmu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/perf/arm_spe_pmu.c +1 -1
@@ -489,7 +489,7 @@ static u64 __arm_spe_pmu_next_off(struct perf_output_handle *handle)* the page boundary following it. Keep the tail boundary if * that's lower. */ -if (handle->wakeup < (handle->head + handle->size) && head <= wakeup) +if ((handle->wakeup - handle->head) < handle->size && head <= wakeup) limit =min (limit,round_up (wakeup,PAGE_SIZE ));if (limit > head)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 983/1424 drm/msm/dpu: Drop sneaky dev_pm_opp_set_rate(0)
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Konrad Dybcio <[email protected]>
[ Upstream commit 811c38907eab0f66c22c5e5708e6f8eab14d76fa ]
dev_pm_opp_set_rate(0) removes the vote specified in required-opps but does not actually park the clock, making it run without the necessary power backing. Prevent that from happening when _dpu_core_perf_get_core_clk_rate() returns 0.
Patchwork: https://patchwork.freedesktop.org/patch/742779/
--- drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c +4 -0
@@ -383,6 +383,10 @@ int dpu_core_perf_crtc_update(struct drm_crtc *crtc,trace_dpu_core_perf_update_clk (kms->dev, !crtc->enabled, clk_rate); +/* If we're going offline, PM callbacks will disable the clocks instead */ +if (!clk_rate) +return 0 ; + clk_rate =min (clk_rate, kms->perf.max_core_clk_rate); ret =dev_pm_opp_set_rate (&kms->pdev->dev, clk_rate);if (ret) {
Signature · 1 line
2.53.0