7.1.6-rc1 review
Subsystems (4)
Greg Kroah-Hartman
maintainerPATCH 123/744 drm/xe/guc: Keep scheduler timeline name alive
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Arvind Yadav <[email protected]>
[ Upstream commit 299bc6d50b1bed7d1f408391736712f01a0855e2 ]
The scheduler keeps a pointer to the timeline name, but q->name is freed with the exec queue while scheduler fences can still reference it.
Store the name in struct xe_guc_exec_queue so it shares the scheduler's RCU-deferred lifetime.
--- drivers/gpu/drm/xe/xe_guc_exec_queue_types.h | 5 +++++ drivers/gpu/drm/xe/xe_guc_submit.c | 4 +++- 2 files changed, 8 insertions(+), 1 deletion(-)
drivers/gpu/drm/xe/xe_guc_exec_queue_types.h +5 -0
@@ -10,6 +10,7 @@#include <linux/workqueue.h> #include "xe_gpu_scheduler_types.h" +#include "xe_hw_fence_types.h" struct dma_fence ;struct xe_exec_queue ;
@@ -24,6 +25,10 @@ struct xe_guc_exec_queue {struct rcu_head rcu;/** @sched: GPU scheduler for this xe_exec_queue */ struct xe_gpu_scheduler sched; +/** +* @name: Scheduler timeline name, kept with @sched until RCU free. +*/ +char name[MAX_FENCE_NAME_LEN ];/** @entity: Scheduler entity for this xe_exec_queue */ struct xe_sched_entity entity;/**
drivers/gpu/drm/xe/xe_guc_submit.c +3 -1
@@ -1973,6 +1973,8 @@ static int guc_exec_queue_init(struct xe_exec_queue *q)xe_exec_queue_assign_name (q, q->guc->id); +strscpy (ge->name, q->name,sizeof (ge->name)); +/* * Use primary queue's submit_wq for all secondary queues of a * multi queue group. This serialization avoids any locking around
@@ -1987,7 +1989,7 @@ static int guc_exec_queue_init(struct xe_exec_queue *q) err =xe_sched_init (&ge->sched, &drm_sched_ops, &xe_sched_ops, submit_wq,xe_lrc_ring_size () /MAX_JOB_SIZE_BYTES ,64 , timeout,guc_to_gt (guc)->ordered_wq,NULL , - q->name,gt_to_xe (q->gt)->drm.dev); + ge->name,gt_to_xe (q->gt)->drm.dev);if (err) goto err_release_id;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 124/744 drm/xe/guc: Hold device ref until queue teardown completes
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Arvind Yadav <[email protected]>
[ Upstream commit 9b7e60184f4b22e893d4ae95234d5f26261a430c ]
GuC exec queue destruction can run asynchronously. If the final device put happens from a destroy worker, drmm cleanup can end up draining the same workqueue and deadlock.
Hold a drm_device reference for the queue lifetime and drop it after queue teardown completes. This keeps drmm cleanup from running while async destroy work is still pending.
Move GuC destroy work to a module-lifetime Xe workqueue and flush it on PCI remove so hot-unbind/rebind still waits for pending destroy work.
With queue-held device refs, guc_submit_sw_fini() cannot run with live GuC IDs. Replace the fini wait with an assertion and remove the unused fini_wq.
v2:
- Rebase
v3:
- Switch to queue-lifetime drm_dev_get()/drm_dev_put() model. (Matt)
- Queue async teardown on system_dfl_wq instead of xe->destroy_wq. (Matt)
- Drop separate deferred drm_dev_put worker.
- Remove stale drain_workqueue(xe->destroy_wq) from guc_submit_sw_fini().
v4:
- Replace the guc_submit_sw_fini() wait with an assertion and remove the now-unused fini_wq. (sashiko)
v5:
- Move destroy work to a module-lifetime Xe workqueue instead of system_dfl_wq. (Matt)
- Flush the module-lifetime destroy workqueue during PCI remove to preserve the old device-remove wait semantics.
v6:
- Keep SVM pagemap destroy work on the per-device destroy_wq to avoid letting it outlive the xe_device/drm_device. (Sashiko)
- Use WQ_MEM_RECLAIM for xe->destroy_wq because SVM pagemap destroy work can be queued from the reclaim path.
v7:
- Drop the per-device xe->destroy_wq and use the module-level destroy WQ for SVM pagemap destroy as well. (Matt)
- Rename xe_exec_queue_destroy_wq_*() helpers to xe_destroy_wq_*() helpers because the WQ is no longer exec-queue specific. (Matt)
v8:
- Rebase.
v9:
- Keep SVM pagemap destroy work on the per-device WQ_MEM_RECLAIM destroy_wq because it can be queued from reclaim and embeds the dev_pagemap used by devres teardown. (Sashiko)
- Keep the module-level destroy WQ GuC-only and drop WQ_MEM_RECLAIM from it.
- Update the module-WQ kdoc to document the GuC/SVM split.
v10:
- Keep xe->destroy_wq per-cpu while adding WQ_MEM_RECLAIM to fix the workqueue allocation warning.
v11:
- Drop the SVM pagemap destroy comment as it was revision-specific. (Thomas)
v12:
- Rebase.
--- drivers/gpu/drm/xe/xe_device.c | 2 +- drivers/gpu/drm/xe/xe_device_types.h | 2 +- drivers/gpu/drm/xe/xe_guc_submit.c | 66 ++++++++++++++++------------ drivers/gpu/drm/xe/xe_guc_types.h | 2 - drivers/gpu/drm/xe/xe_module.c | 49 +++++++++++++++++++++ drivers/gpu/drm/xe/xe_module.h | 5 +++ drivers/gpu/drm/xe/xe_pci.c | 6 +++ 7 files changed, 100 insertions(+), 32 deletions(-)
drivers/gpu/drm/xe/xe_device.c +1 -1
@@ -509,7 +509,7 @@ struct xe_device *xe_device_create(struct pci_dev *pdev, WQ_MEM_RECLAIM); xe->ordered_wq =alloc_ordered_workqueue ("xe-ordered-wq" ,0 ); xe->unordered_wq =alloc_workqueue ("xe-unordered-wq" ,WQ_PERCPU ,0 ); - xe->destroy_wq =alloc_workqueue ("xe-destroy-wq" ,WQ_PERCPU ,0 ); + xe->destroy_wq =alloc_workqueue ("xe-destroy-wq" ,WQ_PERCPU |WQ_MEM_RECLAIM ,0 );if (!xe->ordered_wq || !xe->unordered_wq || !xe->preempt_fence_wq || !xe->destroy_wq) {/*
drivers/gpu/drm/xe/xe_device_types.h +1 -1
@@ -351,7 +351,7 @@ struct xe_device {/** @unordered_wq: used to serialize unordered work */ struct workqueue_struct *unordered_wq; -/** @destroy_wq: used to serialize user destroy work, like queue */ +/** @destroy_wq: used to serialize SVM pagemap destroy work */ struct workqueue_struct *destroy_wq;/** @tiles: device tiles */
drivers/gpu/drm/xe/xe_guc_submit.c +38 -28
144 lines not on this page · raw message
drivers/gpu/drm/xe/xe_guc_types.h +0 -2
@@ -100,8 +100,6 @@ struct xe_guc {* even initialized - before that not even the lock is valid */ bool initialized; -/** @submission_state.fini_wq: submit fini wait queue */ -wait_queue_head_t fini_wq; } submission_state;/** @hwconfig: Hardware config state */
drivers/gpu/drm/xe/xe_module.c +49 -0
67 lines not on this page · raw message
drivers/gpu/drm/xe/xe_module.h +5 -0
@@ -8,6 +8,8 @@#include <linux/types.h> +struct work_struct ; +/* Module modprobe variables */ struct xe_modparam {bool force_execlist;
@@ -27,5 +29,8 @@ struct xe_modparam {extern struct xe_modparam xe_modparam; +bool xe_destroy_wq_queue (struct work_struct *work); +void xe_destroy_wq_flush (void ); +#endif
drivers/gpu/drm/xe/xe_pci.c +6 -0
@@ -1029,6 +1029,12 @@ static void xe_pci_remove(struct pci_dev *pdev)return ;xe_device_remove (xe); + +/* +* Preserve remove-time flush after moving destroy work to module +* lifetime. +*/ +xe_destroy_wq_flush ();xe_pm_fini (xe); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 125/744 ksmbd: pin conn during async oplock break notification
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Qihang <[email protected]>
[ Upstream commit aa5d8f3f96aa11a4a54ce993c11ce8af11c546f9 ]
smb2_oplock_break_noti() and smb2_lease_break_noti() store a ksmbd_conn pointer in an async ksmbd_work and then queue that work on ksmbd-io. The work only increments conn->r_count, which prevents teardown from passing the pending-request wait after the increment, but it does not pin the struct ksmbd_conn object.
If connection teardown races with an oplock break notification, the last conn reference can be dropped before the queued worker finishes. The worker then uses the freed conn in ksmbd_conn_write() and ksmbd_conn_r_count_dec().
Take a real conn reference when publishing the conn pointer to the async work item, and drop it after the notification work has decremented r_count. Apply the same lifetime rule to lease break notification, which uses the same work->conn pattern.
--- fs/smb/server/oplock.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
fs/smb/server/oplock.c +4 -2
@@ -705,6 +705,7 @@ static void __smb2_oplock_break_noti(struct work_struct *wk) out:ksmbd_free_work_struct (work);ksmbd_conn_r_count_dec (conn); +ksmbd_conn_put (conn); }/**
@@ -740,7 +741,7 @@ static int smb2_oplock_break_noti(struct oplock_info *opinfo) br_info->open_trunc = opinfo->open_trunc; work->request_buf = (char *)br_info; - work->conn = conn; + work->conn =ksmbd_conn_get (conn); work->sess = opinfo->sess;ksmbd_conn_r_count_inc (conn);
@@ -814,6 +815,7 @@ static void __smb2_lease_break_noti(struct work_struct *wk) out:ksmbd_free_work_struct (work);ksmbd_conn_r_count_dec (conn); +ksmbd_conn_put (conn); }/**
@@ -853,7 +855,7 @@ static int smb2_lease_break_noti(struct oplock_info *opinfo)memcpy (br_info->lease_key, lease->lease_key,SMB2_LEASE_KEY_SIZE ); work->request_buf = (char *)br_info; - work->conn = conn; + work->conn =ksmbd_conn_get (conn); work->sess = opinfo->sess;ksmbd_conn_r_count_inc (conn);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 126/744 ksmbd: validate compound request size before reading StructureSize2
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xiang Mei (Microsoft) <[email protected]>
[ Upstream commit 15b38176fd1530372905c602fde51fe89ec8c877 ]
When ksmbd validates a compound (chained) SMB2 request, ksmbd_smb2_check_message() reads pdu->StructureSize2 without first checking that the compound element is large enough to contain it. StructureSize2 is a 2-byte field at offset 64 (__SMB2_HEADER_STRUCTURE_SIZE) from the start of each element.
The compound-walking logic only guarantees that a full 64-byte SMB2 header is present for the trailing element: when NextCommand is 0, len is reduced to the number of bytes remaining after next_smb2_rcv_hdr_off. A remote client can craft a compound request whose last element has exactly 64 bytes, so the 2-byte StructureSize2 read at offset 64 extends one byte past the receive buffer, producing a slab-out-of-bounds read.
BUG: KASAN: slab-out-of-bounds in ksmbd_smb2_check_message (fs/smb/server/smb2misc.c:402) Read of size 2 at addr ffff888012ae31ac by task kworker/0:1/14 The buggy address is located 172 bytes inside of allocated 173-byte region Workqueue: ksmbd-io handle_ksmbd_work Call Trace: ... kasan_report (mm/kasan/report.c:595) ksmbd_smb2_check_message (fs/smb/server/smb2misc.c:402) handle_ksmbd_work (fs/smb/server/server.c:119) process_one_work (kernel/workqueue.c:3314) worker_thread (kernel/workqueue.c:3397) kthread (kernel/kthread.c:436) ret_from_fork (arch/x86/kernel/process.c:158) ret_from_fork_asm (arch/x86/entry/entry_64.S:245)
Reject any compound element that is too small to hold StructureSize2 before dereferencing it.
--- fs/smb/server/smb2misc.c | 5 +++++ 1 file changed, 5 insertions(+)
fs/smb/server/smb2misc.c +5 -0
@@ -399,6 +399,11 @@ int ksmbd_smb2_check_message(struct ksmbd_work *work)return 1 ; } +if (len < __SMB2_HEADER_STRUCTURE_SIZE +sizeof (__le16)) { +ksmbd_debug (SMB ,"Message is too small for StructureSize2\n" ); +return 1 ; + } +if (smb2_req_struct_sizes[command] != pdu->StructureSize2) { if (!(command == SMB2_OPLOCK_BREAK_HE && (le16_to_cpu(pdu->StructureSize2) == OP_BREAK_STRUCT_SIZE_20 ||
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 127/744 drm/i915/wm: clear the plane ddb_y entries on plane disable
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vinod Govindapillai <[email protected]>
[ Upstream commit e89978c1cff54e265345c66e1177d19ea5a8bc00 ]
The UV/Y plane DDB entriess are never cleared on sk_wm_plane_disable_noatomic() and can leave stale DDB state for NV12 planes on pre-Gen11 devices
--- drivers/gpu/drm/i915/display/skl_watermark.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/i915/display/skl_watermark.c +1 -1
@@ -3908,7 +3908,7 @@ void skl_wm_plane_disable_noatomic(struct intel_crtc *crtc,return ;skl_ddb_entry_init (&crtc_state->wm.skl.plane_ddb[plane->id],0 ,0 ); -skl_ddb_entry_init (&crtc_state->wm.skl.plane_ddb[plane->id],0 ,0 ); +skl_ddb_entry_init (&crtc_state->wm.skl.plane_ddb_y[plane->id],0 ,0 ); crtc_state->wm.skl.plane_min_ddb[plane->id] =0 ; crtc_state->wm.skl.plane_interim_ddb[plane->id] =0 ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 128/744 drm/i915/selftests: Fix GT PM sort comparators
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Emre Cecanpunar <[email protected]>
[ Upstream commit 612978b83f45bf7018815209db5395d759db6f26 ]
Compare the sampled clock values instead of their addresses. Comparing addresses leaves the samples unsorted, preventing the code from discarding the minimum and maximum samples.
--- drivers/gpu/drm/i915/gt/selftest_gt_pm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/gpu/drm/i915/gt/selftest_gt_pm.c +4 -4
@@ -16,9 +16,9 @@ static int cmp_u64(const void *A, const void *B) {const u64 *a =A , *b =B ; -if (a < b) +if (*a < *b)return -1 ; -else if (a > b) +else if (*a > *b)return 1 ;else return 0 ;
@@ -28,9 +28,9 @@ static int cmp_u32(const void *A, const void *B) {const u32 *a =A , *b =B ; -if (a < b) +if (*a < *b)return -1 ; -else if (a > b) +else if (*a > *b)return 1 ;else return 0 ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 129/744 accel/amdxdna: Fix use-after-free of mm_struct in job scheduler
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lizhi Hou <[email protected]>
[ Upstream commit faebb7ba1ac65fa5810b640df02ce04e509fdc11 ]
amdxdna_cmd_submit() stores current->mm in job->mm without holding any reference. aie2_sched_job_run() later access job->mm from the DRM scheduler worker thread. With only a raw pointer and no structural reference, the mm_struct can be freed before the scheduler runs the job.
Fix this by calling mmgrab() to hold a structural mm_count reference for the lifetime of the job, paired with mmdrop() in every cleanup path.
--- drivers/accel/amdxdna/amdxdna_ctx.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/accel/amdxdna/amdxdna_ctx.c +4 -0
@@ -483,6 +483,7 @@ void amdxdna_sched_job_cleanup(struct amdxdna_sched_job *job)amdxdna_arg_bos_put (job);amdxdna_gem_put_obj (job->cmd_bo);dma_fence_put (job->fence); +mmdrop (job->mm); } int amdxdna_cmd_submit(struct amdxdna_client *client,
@@ -549,6 +550,7 @@ int amdxdna_cmd_submit(struct amdxdna_client *client, job->hwctx = hwctx; job->mm = current->mm; +mmgrab (job->mm); job->fence =amdxdna_fence_create (hwctx);if (!job->fence) {
@@ -583,6 +585,8 @@ int amdxdna_cmd_submit(struct amdxdna_client *client, cmd_put:amdxdna_gem_put_obj (job->cmd_bo); free_job: +if (job->mm) +mmdrop (job->mm);kfree (job);return ret; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 130/744 tcp: fix TIME_WAIT socket reference leak on PSP policy failure
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit 2c1931a81122c3cdc4c89448fe0442c69e21c0d5 ]
Release the TIME_WAIT socket reference and jump to discard_it upon PSP policy failure in both IPv4 and IPv6 receive paths. This prevents a memory leak of tcp_tw_bucket structures.
--- net/ipv4/tcp_ipv4.c | 6 ++++-- net/ipv6/tcp_ipv6.c | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-)
net/ipv4/tcp_ipv4.c +4 -2
@@ -2319,8 +2319,10 @@ int tcp_v4_rcv(struct sk_buff *skb) } drop_reason =psp_twsk_rx_policy_check (inet_twsk (sk), skb); -if (drop_reason) -break ; +if (drop_reason) { +inet_twsk_put (inet_twsk (sk)); + goto discard_it; + } }/* to ACK */ fallthrough;
net/ipv6/tcp_ipv6.c +4 -2
@@ -1962,8 +1962,10 @@ INDIRECT_CALLABLE_SCOPE int tcp_v6_rcv(struct sk_buff *skb) } drop_reason =psp_twsk_rx_policy_check (inet_twsk (sk), skb); -if (drop_reason) -break ; +if (drop_reason) { +inet_twsk_put (inet_twsk (sk)); + goto discard_it; + } }/* to ACK */ fallthrough;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 131/744 dpll: fix NULL pointer dereference in dpll_msg_add_pin_ref_sync()
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ivan Vecera <[email protected]>
[ Upstream commit d2e914a4a0d0f753dbae830264850d044026167c ]
When a dpll_pin is shared across multiple dpll_device instances and those devices are being unregistered (e.g. during driver module removal), a NULL pointer dereference can occur in dpll_msg_add_pin_ref_sync().
This happens under the following conditions:
- A pin is registered with two or more dpll devices (dpll_A, dpll_B)
- The pin has ref_sync pairs with other pins
- During unregistration of dpll_A's pins, a ref_sync partner pin is unregistered first, removing it from dpll_A->pin_refs
- But since the partner pin is still registered with dpll_B, its dpll_refs is not empty, so dpll_pin_ref_sync_pair_del() does NOT run and the partner stays in the pin's ref_sync_pins xarray
- When the pin itself is then unregistered from dpll_A, the delete notification calls dpll_msg_add_pin_ref_sync() which finds the partner in ref_sync_pins, passes dpll_pin_available() (partner is still registered with dpll_B), but dpll_pin_on_dpll_priv(dpll_A, partner) returns NULL because partner was already removed from dpll_A->pin_refs
- The NULL priv pointer is passed to the driver's ref_sync_get callback, which dereferences it
BUG: kernel NULL pointer dereference, address: 0000000000000034 Oops: Oops: 0000 [#1] SMP NOPTI RIP: 0010:zl3073x_dpll_input_pin_ref_sync_get+0x73/0x80 [zl3073x] Call Trace: dpll_msg_add_pin_ref_sync+0xb8/0x200 dpll_cmd_pin_get_one+0x3b6/0x4b0 dpll_pin_event_send+0x72/0x140 __dpll_pin_unregister+0x5a/0x2b0 dpll_pin_unregister+0x49/0x70
Fix this by skipping ref_sync pins whose priv pointer cannot be resolved for the current dpll device.
--- drivers/dpll/dpll_netlink.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/dpll/dpll_netlink.c +3 -0
@@ -557,6 +557,9 @@ dpll_msg_add_pin_ref_sync(struct sk_buff *msg, struct dpll_pin *pin,if (!dpll_pin_available (ref_sync_pin))continue ; ref_sync_pin_priv =dpll_pin_on_dpll_priv (dpll, ref_sync_pin); +/* Pin may have been unregistered from this dpll already */ +if (!ref_sync_pin_priv) +continue ;if (WARN_ON (!ops->ref_sync_get))return -EOPNOTSUPP ; ret = ops->ref_sync_get(pin, pin_priv, ref_sync_pin,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 132/744 net/sched: act_tunnel_key: Defer dst_release to RCU callback
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jamal Hadi Salim <[email protected]>
[ Upstream commit f1f5c8a3955f8fda3f84ed883ac8daa1847e724c ]
Fix a race-condition use-after-free in tunnel_key_release_params().
The function releases the metadata_dst of the old params synchronously via dst_release() while deferring the params struct free with kfree_rcu(). A concurrent tunnel_key_act() reader on the datapath may still hold the old params pointer (under rcu_read_lock_bh) and proceed to call dst_clone(¶ms->tcft_enc_metadata->dst) after the writer's dst_release has already pushed the dst's rcuref to RCUREF_DEAD.
[email protected] produced a poc which i (and Victor) verified that KASAN reports:
==================================================================
BUG: KASAN: slab-use-after-free in instrument_atomic_read_write include/linux/instrumented.h:112 BUG: KASAN: slab-use-after-free in atomic_sub_return_release include/linux/atomic/atomic-instrumented.h:326 BUG: KASAN: slab-use-after-free in __rcuref_put include/linux/rcuref.h:109 BUG: KASAN: slab-use-after-free in rcuref_put include/linux/rcuref.h:173 BUG: KASAN: slab-use-after-free in dst_release+0x5b/0x370 net/core/dst.c:168 Write of size 4 at addr ffff88806158de40 by task poc/9388 CPU: 0 UID: 0 PID: 9388 Comm: poc Tainted: G W 7.1.0-rc7 #7 PREEMPT(lazy) Tainted: [W]=WARN Hardware name: QEMU Ubuntu 25.10 PC v2 (i440FX + PIIX, + 10.1 machine, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014 Call Trace: <TASK> __dump_stack lib/dump_stack.c:94 dump_stack_lvl+0x100/0x190 lib/dump_stack.c:120 print_address_description mm/kasan/report.c:378 print_report+0x139/0x4ad mm/kasan/report.c:482 kasan_report+0xe4/0x1d0 mm/kasan/report.c:595 check_region_inline mm/kasan/generic.c:186 kasan_check_range+0x125/0x200 mm/kasan/generic.c:200 instrument_atomic_read_write include/linux/instrumented.h:112 atomic_sub_return_release include/linux/atomic/atomic-instrumented.h:326 __rcuref_put include/linux/rcuref.h:109 rcuref_put include/linux/rcuref.h:173 dst_release+0x5b/0x370 net/core/dst.c:168 refdst_drop include/net/dst.h:272 skb_dst_drop include/net/dst.h:284 skb_release_head_state+0x293/0x400 net/core/skbuff.c:1163 skb_release_all net/core/skbuff.c:1187 [..] Allocated by task 9391: kasan_save_stack+0x30/0x50 mm/kasan/common.c:57 kasan_save_track+0x14/0x30 mm/kasan/common.c:78 poison_kmalloc_redzone mm/kasan/common.c:398 __kasan_kmalloc+0x9a/0xb0 mm/kasan/common.c:415 kasan_kmalloc include/linux/kasan.h:263 __do_kmalloc_node mm/slub.c:5296 __kmalloc_noprof+0x2f1/0x830 mm/slub.c:5308 kmalloc_noprof include/linux/slab.h:954 kzalloc_noprof include/linux/slab.h:1188 offload_action_alloc+0x2f/0x130 net/core/flow_offload.c:35 tcf_action_offload_add_ex+0x1ba/0x880 net/sched/act_api.c:258 tcf_action_offload_add net/sched/act_api.c:293 tcf_action_init+0x66e/0xa20 net/sched/act_api.c:1547 tcf_action_add+0xf6/0x5d0 net/sched/act_api.c:2101 [..] Freed by task 9391: kasan_save_stack+0x30/0x50 mm/kasan/common.c:57 kasan_save_track+0x14/0x30 mm/kasan/common.c:78 kasan_save_free_info+0x3b/0x70 mm/kasan/generic.c:584 poison_slab_object mm/kasan/common.c:253 __kasan_slab_free+0x6b/0x90 mm/kasan/common.c:285 kasan_slab_free include/linux/kasan.h:235 slab_free_hook mm/slub.c:2689 slab_free mm/slub.c:6251 kfree+0x21f/0x6b0 mm/slub.c:6566 tcf_action_offload_add_ex+0x4ad/0x880 net/sched/act_api.c:284 tcf_action_offload_add net/sched/act_api.c:293 tcf_action_init+0x66e/0xa20 net/sched/act_api.c:1547 tcf_action_add+0xf6/0x5d0 net/sched/act_api.c:2101 The buggy address belongs to the object at ffff88806158de00 which belongs to the cache kmalloc-256 of size 256
The buggy address is located 64 bytes inside of
freed 256-byte region [ffff88806158de00, ffff88806158df00)
The buggy address belongs to the physical page: page: refcount:0 mapcount:0 mapping:0000000000000000 index:0xffff88806158d600 pfn:0x6158c head: order:1 mapcount:0 entire_mapcount:0 nr_pages_mapped:0 pincount:0 flags: 0x4fff00000000240(workingset|head|node=1|zone=1|lastcpupid=0x7ff) page_type: f5(slab) raw: 04fff00000000240 ffff88801c841b40 ffffea0001856290 ffffea0001856190 raw: ffff88806158d600 0000000800100009 00000000f5000000 0000000000000000
head: 04fff00000000240 ffff88801c841b40 ffffea0001856290 ffffea0001856190
head: ffff88806158d600 0000000800100009 00000000f5000000 0000000000000000
head: 04fff00000000001 ffffffffffffff81 00000000ffffffff 00000000ffffffff
head: ffffffffffffffff 0000000000000000 00000000ffffffff 0000000000000002
page dumped because: kasan: bad access detected page_owner tracks the page as allocated page last allocated via order 1, migratetype Unmovable, gfp_mask 0xd2820(GFP_ATOMIC|__GFP_NOWARN|__GFP_NORETRY|__GFP_COMP|__GFP_NOMEMALLOC), pid 9391, tgid 9378 (poc), ts 123227323196, free_ts 0 set_page_owner include/linux/page_owner.h:32 post_alloc_hook+0xfe/0x140 mm/page_alloc.c:1853 prep_new_page mm/page_alloc.c:1861 get_page_from_freelist+0x110c/0x2fc0 mm/page_alloc.c:3941 __alloc_frozen_pages_noprof+0x263/0x2bc0 mm/page_alloc.c:5221 alloc_slab_page mm/slub.c:3278 allocate_slab mm/slub.c:3467 new_slab+0xa6/0x690 mm/slub.c:3525 refill_objects+0x271/0x420 mm/slub.c:7272 refill_sheaf mm/slub.c:2816 __pcs_replace_empty_main+0x373/0x630 mm/slub.c:4652 alloc_from_pcs mm/slub.c:4750 slab_alloc_node mm/slub.c:4884 __do_kmalloc_node mm/slub.c:5295 __kmalloc_noprof+0x66d/0x830 mm/slub.c:5308 kmalloc_noprof include/linux/slab.h:954 metadata_dst_alloc+0x26/0x90 net/core/dst.c:298 tun_rx_dst include/net/dst_metadata.h:144 __ip_tun_set_dst include/net/dst_metadata.h:208 tunnel_key_init+0xb01/0x1b90 net/sched/act_tunnel_key.c:451 tcf_action_init_1+0x46b/0x6c0 net/sched/act_api.c:1428 tcf_action_init+0x448/0xa20 net/sched/act_api.c:1503 tcf_action_add+0xf6/0x5d0 net/sched/act_api.c:2101
[..]
==================================================================
Fix by moving dst_release() into a custom RCU callback that runs after the grace period, matching the lifetime of the containing params struct. Readers in the datapath therefore always find a live rcuref when calling dst_clone().
--- net/sched/act_tunnel_key.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-)
net/sched/act_tunnel_key.c +10 -4
@@ -342,14 +342,20 @@ static const struct nla_policy tunnel_key_policy[TCA_TUNNEL_KEY_MAX + 1] = { [TCA_TUNNEL_KEY_ENC_TTL] = { .type = NLA_U8 }, }; -static void tunnel_key_release_params (struct tcf_tunnel_key_params *p) +static void tunnel_key_release_params_rcu (struct rcu_head *head) { -if (!p) -return ; +struct tcf_tunnel_key_params *p =container_of (head,typeof (*p), rcu); +if (p->tcft_action ==TCA_TUNNEL_KEY_ACT_SET )dst_release (&p->tcft_enc_metadata->dst); +kfree (p); +} -kfree_rcu (p, rcu); +static void tunnel_key_release_params (struct tcf_tunnel_key_params *p) +{ +if (!p) +return ; +call_rcu (&p->rcu, tunnel_key_release_params_rcu); } static int tunnel_key_init(struct net *net, struct nlattr *nla,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 133/744 sctp: fix auth_hmacs array size in struct sctp_cookie
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xin Long <[email protected]>
[ Upstream commit e0b5252a59383b77d1b8dbeda00b7184dd95f4d3 ]
The auth_hmacs array in struct sctp_cookie is supposed to store a complete SCTP_AUTH_HMAC_ALGO parameter, which consists of a struct sctp_paramhdr followed by N HMAC identifiers.
However, the array size was calculated using an extra 2 bytes instead of sizeof(struct sctp_paramhdr), which is 4 bytes. When four HMAC identifiers are configured, the HMAC-ALGO parameter stored in the endpoint is larger than the auth_hmacs buffer in the cookie.
As a result, sctp_association_init() copies beyond the end of auth_hmacs when initializing the association, corrupting the adjacent auth_chunks field. This can lead to an invalid HMAC identifier being accepted and later cause an out-of-bounds read in sctp_auth_get_hmac().
Fix the array size calculation by including the full SCTP parameter header size.
--- include/net/sctp/structs.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
include/net/sctp/structs.h +2 -1
@@ -312,7 +312,8 @@ struct sctp_cookie {__u8 auth_random[sizeof (struct sctp_paramhdr ) +SCTP_AUTH_RANDOM_LENGTH ]; -__u8 auth_hmacs[SCTP_AUTH_NUM_HMACS *sizeof (__u16) +2 ]; +__u8 auth_hmacs[sizeof (struct sctp_paramhdr ) + +SCTP_AUTH_NUM_HMACS *sizeof (__u16)];__u8 auth_chunks[sizeof (struct sctp_paramhdr ) +SCTP_AUTH_MAX_CHUNKS ];/* This is a shim for my peer's INIT packet, followed by
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 134/744 bnxt_en: Handle partially initialized auxiliary devices
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ruoyu Wang <[email protected]>
[ Upstream commit 1cb8553c02e93e5a150cebd42f9ee3db0ece4707 ]
bnxt_aux_devices_init() calls auxiliary_device_init() before all fields used by bnxt_aux_dev_release() are initialized. After auxiliary_device_init() succeeds, later errors must unwind with auxiliary_device_uninit(), which invokes the release callback.
The release callback assumes that aux_priv->id, aux_priv->edev, edev->net and edev->ulp_tbl are all populated. If allocation fails after auxiliary_device_init(), the release path can otherwise dereference or clear partially initialized state.
Allocate and attach the bnxt_en_dev and ULP table before calling auxiliary_device_init(), so the release callback only sees a fully initialized auxiliary private object. If auxiliary_device_init() itself fails, free those allocations directly because device_initialize() has not run and the release callback will not be invoked.
This issue was found by a static analysis checker and confirmed by manual source review.
--- drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c | 39 ++++++++++--------- 1 file changed, 20 insertions(+), 19 deletions(-)
drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c +20 -19
@@ -566,6 +566,18 @@ void bnxt_aux_devices_init(struct bnxt *bp)if (!aux_priv) goto next_auxdev; + edev =kzalloc_obj (*edev); +if (!edev) + goto aux_priv_free; + aux_priv->edev = edev; +bnxt_set_edev_info (edev, bp); + + ulp =kzalloc_obj (*ulp); +if (!ulp) + goto edev_free; + edev->ulp_tbl = ulp; + aux_priv->id = idx; + aux_dev = &aux_priv->aux_dev; aux_dev->id = bp->auxdev_id; aux_dev->name = bnxt_aux_devices[idx].name;
@@ -573,37 +585,26 @@ void bnxt_aux_devices_init(struct bnxt *bp) aux_dev->dev.release = bnxt_aux_dev_release; rc =auxiliary_device_init (aux_dev); -if (rc) { -kfree (aux_priv); - goto next_auxdev; - } +if (rc) + goto ulp_free; bp->aux_priv[idx] = aux_priv;/* From this point, all cleanup will happen via the .release * callback & any error unwinding will need to include a call * to auxiliary_device_uninit. */ - edev =kzalloc_obj (*edev); -if (!edev) - goto aux_dev_uninit; - - aux_priv->edev = edev; -bnxt_set_edev_info (edev, bp); - - ulp =kzalloc_obj (*ulp); -if (!ulp) - goto aux_dev_uninit; - - edev->ulp_tbl = ulp; bp->edev[idx] = edev;if (idx ==BNXT_AUXDEV_RDMA ) bp->ulp_num_msix_want =bnxt_set_dflt_ulp_msix (bp); - aux_priv->id = idx;bnxt_auxdev_set_state (bp, idx,BNXT_ADEV_STATE_INIT );continue ; -aux_dev_uninit: -auxiliary_device_uninit (aux_dev); +ulp_free: +kfree (ulp); +edev_free: +kfree (edev); +aux_priv_free: +kfree (aux_priv); next_auxdev:if (idx ==BNXT_AUXDEV_RDMA ) bp->flags &= ~BNXT_FLAG_ROCE_CAP ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 135/744 selftests: netconsole: only restore MAC when it changed on resume
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andre Carvalho <[email protected]>
[ Upstream commit 04aeddf2dadd0eb7ad016a766dcbe9c983311f09 ]
The "mac" bind mode reactivation downs the interface, restores the saved MAC and renames it to trigger a target resume. This assumes the recreated interface comes back with a different MAC, which is true under MACAddressPolicy=none (as on the Netdev CI) but not when MACs are persistent. In the persistent case netconsole resumes the target on its own, and the down/restore/rename flow instead drops it and fails the test.
Guard the block on the MAC having actually changed so the test passes under both policies.
--- .../testing/selftests/drivers/net/netconsole/netcons_resume.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
tools/testing/selftests/drivers/net/netconsole/netcons_resume.sh +2 -1
@@ -44,7 +44,8 @@ function trigger_reactivation() { # Restore MACs ip netns exec "${NAMESPACE}" ip link set "${DSTIF}" \ address "${SAVED_DSTMAC}" - if [ "${BINDMODE}" == "mac" ]; then + if [ "${BINDMODE}" == "mac" ] && + [ "$(mac_get "${SRCIF}")" != "${SAVED_SRCMAC}" ]; then ip link set dev "${SRCIF}" down ip link set dev "${SRCIF}" address "${SAVED_SRCMAC}" # Rename device in order to trigger target resume, as initial
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 136/744 mpls: fix NULL deref in mpls_valid_fib_dump_req() on CONFIG_INET=n
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Weiming Shi <[email protected]>
[ Upstream commit 56d96fededd61192cd7cc8d2b0f36adfd59036c3 ]
On CONFIG_INET=n builds, mpls_valid_fib_dump_req() walks the parsed attribute table itself instead of calling ip_valid_fib_dump_req(). The RTA_OIF arm passes tb[RTA_OIF] to nla_get_u32() without checking it is present, so an RTM_GETROUTE dump for AF_MPLS with strict checking and no RTA_OIF hits a NULL dereference.
RTM_GETROUTE is RTNL_KIND_GET, which rtnetlink_rcv_msg() permits without CAP_NET_ADMIN, so an unprivileged user can trigger it.
Oops: general protection fault, probably for non-canonical address
0xdffffc0000000000: 0000 [#1] SMP KASAN NOPTI
KASAN: null-ptr-deref in range [0x0000000000000000-0x0000000000000007]
RIP: 0010:mpls_valid_fib_dump_req (net/mpls/af_mpls.c:2189)
Call Trace:
mpls_dump_routes (net/mpls/af_mpls.c:2236)
netlink_dump (net/netlink/af_netlink.c:2331)
__netlink_dump_start (net/netlink/af_netlink.c:2446)
rtnetlink_rcv_msg (net/core/rtnetlink.c:7033)
netlink_rcv_skb (net/netlink/af_netlink.c:2556)
netlink_unicast (net/netlink/af_netlink.c:1345)
netlink_sendmsg (net/netlink/af_netlink.c:1900)
__sock_sendmsg (net/socket.c:790)
____sys_sendmsg (net/socket.c:2684)
___sys_sendmsg (net/socket.c:2738)
__sys_sendmsg (net/socket.c:2770)
do_syscall_64 (arch/x86/entry/syscall_64.c:94)
entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121)Skip unset attributes, as ip_valid_fib_dump_req() does.
--- net/mpls/af_mpls.c | 3 +++ 1 file changed, 3 insertions(+)
net/mpls/af_mpls.c +3 -0
@@ -2186,6 +2186,9 @@ static int mpls_valid_fib_dump_req(struct net *net, const struct nlmsghdr *nlh,int ifindex;if (i ==RTA_OIF ) { +if (!tb[i]) +continue ; + ifindex =nla_get_u32 (tb[i]); filter->dev =dev_get_by_index_rcu (net, ifindex);if (!filter->dev)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 137/744 usb: core: sysfs: add lock to bos_descriptors_read()
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Griffin Kroah-Hartman <[email protected]>
commit 4e0197fbb0eec588795d5431716a244d9ac8fa93 upstream.
Add a lock to the function bos_descriptors_read().
This function accesses udev->bos, which could be simultaneously freed in usb_reset_and_verify_device(), a function that is commonly called in drivers all over the kernel.
--- drivers/usb/core/sysfs.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
drivers/usb/core/sysfs.c +7 -1
@@ -899,10 +899,15 @@ bos_descriptors_read(struct file *filp, {struct device *dev =kobj_to_dev (kobj);struct usb_device *udev =to_usb_device (dev); -struct usb_host_bos *bos = udev->bos; +struct usb_host_bos *bos;struct usb_bos_descriptor *desc;size_t desclen, n =0 ; +int rc; + rc =usb_lock_device_interruptible (udev); +if (rc <0 ) +return -EINTR ; + bos = udev->bos;if (bos) { desc = bos->desc; desclen =le16_to_cpu (desc->wTotalLength);
@@ -911,6 +916,7 @@ bos_descriptors_read(struct file *filp,memcpy (buf, (void *) desc + off, n); } } +usb_unlock_device (udev);return n; } static const BIN_ATTR_RO(bos_descriptors, 65535); /* max-size BOS */
Greg Kroah-Hartman
maintainerPATCH 138/744 wifi: at76c50x-usb: avoid length underflow in at76_guess_freq()
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Huihui Huang <[email protected]>
commit 61a799ffd1e5a4fd3702d547828b7ff3d161468e upstream.
at76_guess_freq() checks only that the received frame is at least a bare 802.11 header (24 bytes) before subtracting the fixed management-body offset:
len -= el_off;
For both beacon and probe response frames, el_off is 36. If the frame is shorter than el_off, subtracting it causes the calculated IE length to wrap. The length is eventually passed to cfg80211_find_elem_match() as a very large unsigned value, so the element walk runs beyond the RX skb.
This path is reached from at76_rx_tasklet() while scanning. If the device delivers a truncated beacon or probe response, the oversized IE length causes an out-of-bounds read during scanning.
Skip the IE lookup if the frame does not reach the variable elements, before subtracting el_off.
--- drivers/net/wireless/atmel/at76c50x-usb.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
drivers/net/wireless/atmel/at76c50x-usb.c +5 -2
@@ -1521,13 +1521,16 @@ static inline int at76_guess_freq(structif (ieee80211_is_probe_resp (hdr->frame_control)) { el_off = offsetof(struct ieee80211_mgmt, u.probe_resp.variable); - el = ((struct ieee80211_mgmt *)hdr)->u.probe_resp.variable; }else if (ieee80211_is_beacon (hdr->frame_control)) { el_off = offsetof(struct ieee80211_mgmt, u.beacon.variable); - el = ((struct ieee80211_mgmt *)hdr)->u.beacon.variable; }else { goto exit; } + +if (len < el_off) + goto exit; + + el = priv->rx_skb->data + el_off; len -= el_off; el =cfg80211_find_ie (WLAN_EID_DS_PARAMS , el, len);
Greg Kroah-Hartman
maintainerPATCH 139/744 usb: core: port: Deattach Type-C connector on component unbind
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chia-Lin Kao (AceLan) <[email protected]>
commit e0b291fe117964037e0ba382eff4bb365d531c3a upstream.
connector_unbind() is the mirror of connector_bind(), but it is missing the symmetric call to typec_deattach() that connector_bind() makes via:
if (port_dev->child)
typec_attach(port_dev->connector, &port_dev->child->dev);When a Thunderbolt dock is unplugged, two teardown paths race:
1. The component framework calls connector_unbind() first, which sets port_dev->connector = NULL without calling typec_deattach(). This leaves port->usb2_dev/port->usb3_dev in struct typec_port pointing at the USB device that is about to be freed.
2. usb_disconnect() then calls typec_deattach(port_dev->connector, ...), but port_dev->connector is already NULL, so the call is a no-op and port->usb2_dev is never cleared.
3. Concurrently, UCSI detects a PD partner-disconnect event and calls typec_unregister_partner(), which reads port->usb2_dev (now a dangling pointer to freed memory) and passes it to typec_partner_unlink_device() -> sysfs_remove_link() -> dev_name() on the freed device, corrupting the typec/UCSI partner state.
This corruption leaves the Thunderbolt tunnel in an inconsistent state on the next dock hot-plug. On affected hardware the dock's I225/igc NIC fails to enumerate: AER fires a slot reset while the igc driver is still initialising ("PCIe link lost"), and the subsequent igc_reset attempt hits igc_rd32 on an already-detached device:
igc 0000:2e:00.0 eth0: PCIe link lost, device now detached
igc: Failed to read reg 0x0!
WARNING: CPU: 9 PID: 129 at drivers/net/ethernet/intel/igc/igc_main.c:7005
igc_rd32+0xa4/0xc0 [igc]
Call Trace:
igc_disable_pcie_master+0x16/0xa0 [igc]
igc_reset_hw_base+0x14/0x170 [igc]
igc_reset+0x63/0x110 [igc]
igc_io_slot_reset+0x9e/0xd0 [igc]
report_slot_reset+0x5d/0xc0
pcie_do_recovery+0x209/0x400
aer_isr_one_error_type+0x235/0x430
aer_isr+0x4e/0x80
irq_thread+0xf4/0x1f04. UCSI later handles the PD partner-disconnect and calls typec_unregister_partner(), which still sees the stale port->usb2_dev and tries to remove its sysfs link a second time:
kernfs: can not remove 'typec', no directory
WARNING: CPU: 6 PID: 55 at fs/kernfs/dir.c:1706 kernfs_remove_by_name_ns+0xe9/0xf0
Workqueue: events ucsi_handle_connector_change [typec_ucsi]
Call Trace:
sysfs_remove_link+0x19/0x50
typec_unregister_partner+0x6e/0x120 [typec]
ucsi_unregister_partner+0x107/0x150 [typec_ucsi]
ucsi_handle_connector_change+0x3ec/0x490 [typec_ucsi]
process_one_work+0x18e/0x3e0
worker_thread+0x2e3/0x420
kthread+0x10a/0x230
ret_from_fork+0x121/0x140
ret_from_fork_asm+0x1a/0x30With worse timing the same stale pointer is dereferenced after the backing memory is freed, turning the warning into a use-after-free.
Fix the asymmetry: call typec_deattach() before clearing port_dev->connector, matching what connector_bind() does on the bind side. typec_partner_deattach() is already protected by port->partner_link_lock, so it serialises safely with the concurrent typec_unregister_partner() path.
--- drivers/usb/core/port.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/usb/core/port.c +2 -0
@@ -740,6 +740,8 @@ static void connector_unbind(struct devisysfs_remove_link (&connector->kobj,dev_name (dev));sysfs_remove_link (&dev->kobj,"connector" ); +if (port_dev->child) +typec_deattach (port_dev->connector, &port_dev->child->dev); port_dev->connector =NULL ; }
Greg Kroah-Hartman
maintainerPATCH 140/744 usb: musb: omap2430: Do not put borrowed of_node in probe
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guangshuo Li <[email protected]>
commit c947360ae63eee1c9eacc030dd6f5a53f717addf upstream.
omap2430_probe() stores pdev->dev.of_node in a local np variable. This is a borrowed pointer and the probe function does not take a reference to it.
The success and error paths nevertheless call of_node_put(np). This drops a reference that is owned by the platform device, and can leave pdev->dev.of_node with an unbalanced reference count.
Do not put the borrowed platform device node from omap2430_probe(). References taken for the child MUSB device are handled by the device core, and the ctrl-module phandle reference is still released separately.
--- drivers/usb/musb/omap2430.c | 2 -- 1 file changed, 2 deletions(-)
drivers/usb/musb/omap2430.c +0 -2
@@ -454,7 +454,6 @@ static int omap2430_probe(struct platfordev_err (&pdev->dev,"failed to register musb device\n" ); goto err_disable_rpm; } -of_node_put (np);return 0 ;
@@ -464,7 +463,6 @@ err_put_control_otghs:if (!IS_ERR (glue->control_otghs))put_device (glue->control_otghs); err_put_musb: -of_node_put (np);platform_device_put (musb);return ret;
Greg Kroah-Hartman
maintainerPATCH 141/744 USB: storage: add NO_ATA_1X quirk for Longmai USB Key
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Huang Wei <[email protected]>
commit 3b4ca2e01c1dd8c00b675b794732945f460a471b upstream.
The Longmai Technologies USB Key (0x04b4:0xb708) advertises itself as a SCSI/Bulk-only mass storage device but does not correctly handle ATA pass-through commands. When such a command (ATA_12 or ATA_16) is sent to the device it fails to respond and the transfer eventually times out, leaving the device unusable.
Add an unusual_devs entry for this device that sets the US_FL_NO_ATA_1X flag, so usb-storage short-circuits ATA pass-through commands and returns INVALID COMMAND OPERATION CODE (0x20 0x05 0x24 0x00) instead of forwarding them to the device.
Information about the device in /sys/kernel/debug/usb/devices:
T: Bus=02 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 12 Spd=480 MxCh= 0 D: Ver= 2.00 Cls=00(>ifc ) Sub=06 Prot=50 MxPS=64 #Cfgs= 1 P: Vendor=04b4 ProdID=b708 Rev= 1.00 S: Manufacturer=Longmai Technologies S: Product=USB Key C:* #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=100mA I:* If#= 0 Alt= 0 #EPs= 2 Cls=08(stor.) Sub=06 Prot=50 Driver=usb-storage E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
--- drivers/usb/storage/unusual_devs.h | 7 +++++++ 1 file changed, 7 insertions(+)
drivers/usb/storage/unusual_devs.h +7 -0
@@ -395,6 +395,13 @@ UNUSUAL_DEV( 0x04b3, 0x4001, 0x0110, 0x USB_SC_DEVICE, USB_PR_CB, NULL, US_FL_MAX_SECTORS_MIN), +/* Reported by Ai Chao <[email protected]> */ +UNUSUAL_DEV (0x04b4 ,0xb708 ,0x0000 ,0xffff , +"Longmai Technologies" , +"USB Key" , +USB_SC_SCSI ,USB_PR_BULK ,NULL , + US_FL_NO_ATA_1X), +/* * Reported by Simon Levitt <[email protected]> * This entry needs Sub and Proto fields
Greg Kroah-Hartman
maintainerPATCH 142/744 usb: chipidea: fix usage_count leak when autosuspend_delay is negative
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xu Yang <[email protected]>
commit fc3afb5728e297994863f8a2a01b88a920bbf53e upstream.
The probe() calls pm_runtime_use_autosuspend(), but remove() does not call pm_runtime_dont_use_autosuspend(). This can lead to a usage_count leak if autosuspend_delay is set to a negative value.
The pm_runtime_use_autosuspend() also notes that it's important to undo this with pm_runtime_dont_use_autosuspend() at driver exit time.
--- drivers/usb/chipidea/core.c | 1 + 1 file changed, 1 insertion(+)
drivers/usb/chipidea/core.c +1 -0
@@ -1253,6 +1253,7 @@ static void ci_hdrc_remove(struct platfousb_role_switch_unregister (ci->role_switch);if (ci->supports_runtime_pm) { +pm_runtime_dont_use_autosuspend (&pdev->dev);pm_runtime_get_sync (&pdev->dev);pm_runtime_disable (&pdev->dev);pm_runtime_put_noidle (&pdev->dev);
Greg Kroah-Hartman
maintainerPATCH 143/744 usb: gadget: dummy_hcd: prevent fifo_req reuse during giveback
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jinchao Wang <[email protected]>
commit d5e5cd3654d2b5359a12ea6586120f05b28634ee upstream.
dummy_hcd embeds a single shared usb_request (dum->fifo_req) that the "emulated single-request FIFO" fast-path in dummy_queue() reuses for small IN transfers: it copies the caller's request into it (req->req = *_req) and queues it, treating list_empty(&fifo_req.queue) as "the slot is free".
The completion side (dummy_timer/transfer/nuke/dummy_dequeue) follows the standard pattern: list_del_init(&req->queue) unlinks the request, then the lock is dropped and usb_gadget_giveback_request() invokes req->complete(). But list_del_init() makes fifo_req.queue look empty *before* the completion callback returns, so a concurrent dummy_queue() on another CPU sees the slot as free, reuses fifo_req and runs req->req = *_req -- overwriting req->complete while dummy_timer is mid-calling it. The indirect call then jumps to a clobbered pointer, causing a general protection fault / page fault in dummy_timer (syzkaller extid faf3a6cf579fc65591ca). The clobbering write is an in-bounds memcpy on a live shared object, so KASAN cannot flag it.
Add a fifo_req_busy bit covering the shared request's whole lifetime:
set it in dummy_queue() when the FIFO fast-path takes fifo_req (making it the fast-path guard, replacing the list_empty(&fifo_req.queue) test), and clear it after the completion callback has returned, via a dummy_giveback() helper used at all four gadget-request giveback sites. The shared slot can no longer be reused until its completion callback has finished.
--- drivers/usb/gadget/udc/dummy_hcd.c | 40 ++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 13 deletions(-)
drivers/usb/gadget/udc/dummy_hcd.c +27 -13
@@ -278,6 +278,7 @@ struct dummy { unsigned ints_enabled:1; unsigned udc_suspended:1; unsigned pullup:1; + unsigned fifo_req_busy:1;/* * HOST side support
@@ -329,6 +330,26 @@ static inline struct dummy *gadget_dev_t/* DEVICE/GADGET SIDE UTILITY ROUTINES */ +/* +* Give back a gadget request with dum->lock dropped around the callback. +* If @req is the shared fifo_req, clear fifo_req_busy afterward: the flag +* was set in dummy_queue() when the shared request was taken and must stay +* set until its completion callback has returned; list_del_init() alone +* makes the request look idle while the callback is still running. +* Caller holds dum->lock and has already done list_del_init() + status. +*/ +static void dummy_giveback (struct dummy *dum,struct usb_ep *_ep, +struct dummy_request *req) +{ +bool fifo = req == &dum->fifo_req; + +spin_unlock (&dum->lock); +usb_gadget_giveback_request (_ep, &req->req); +spin_lock (&dum->lock); +if (fifo) + dum->fifo_req_busy =0 ; +} +/* called with spinlock held */ static void nuke (struct dummy *dum,struct dummy_ep *ep) {
@@ -339,9 +360,7 @@ static void nuke(struct dummy *dum, strulist_del_init (&req->queue); req->req.status = -ESHUTDOWN ; -spin_unlock (&dum->lock); -usb_gadget_giveback_request (&ep->ep, &req->req); -spin_lock (&dum->lock); +dummy_giveback (dum, &ep->ep, req); } }
@@ -728,10 +747,11 @@ static int dummy_queue(struct usb_ep *_e/* implement an emulated single-request FIFO */ if (ep->desc && (ep->desc->bEndpointAddress &USB_DIR_IN ) && -list_empty (&dum->fifo_req.queue) && + !dum->fifo_req_busy &&list_empty (&ep->queue) && _req->length <=FIFO_SIZE ) { req = &dum->fifo_req; + dum->fifo_req_busy =1 ; req->req = *_req; req->req.buf = dum->fifo_buf;memcpy (dum->fifo_buf, _req->buf, _req->length);
@@ -785,9 +805,7 @@ static int dummy_dequeue(struct usb_ep *dev_dbg (udc_dev (dum),"dequeued req %p from %s, len %d buf %p\n" , req, _ep->name, _req->length, _req->buf); -spin_unlock (&dum->lock); -usb_gadget_giveback_request (_ep, _req); -spin_lock (&dum->lock); +dummy_giveback (dum, _ep, req); }spin_unlock_irqrestore (&dum->lock, flags);return retval;
@@ -1523,9 +1541,7 @@ top:if (req->req.status != -EINPROGRESS ) {list_del_init (&req->queue); -spin_unlock (&dum->lock); -usb_gadget_giveback_request (&ep->ep, &req->req); -spin_lock (&dum->lock); +dummy_giveback (dum, &ep->ep, req);/* requests might have been unlinked... */ rescan =1 ;
@@ -1910,9 +1926,7 @@ restart:dev_dbg (udc_dev (dum),"stale req = %p\n" , req); -spin_unlock (&dum->lock); -usb_gadget_giveback_request (&ep->ep, &req->req); -spin_lock (&dum->lock); +dummy_giveback (dum, &ep->ep, req); ep->already_seen =0 ; goto restart; }
Greg Kroah-Hartman
maintainerPATCH 144/744 usb: gadget: f_midi: cancel pending IN work before freeing the midi object
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Fan Wu <[email protected]>
commit 5650c18d93a1db7e27cb5a40b394747eb4686d5b upstream.
The f_midi driver embeds a work item (midi->work) whose handler, f_midi_in_work(), dereferences the enclosing struct f_midi through container_of(). This work is armed from two sites: f_midi_complete(), on a normal IN-endpoint completion, and f_midi_in_trigger(), on an ALSA rawmidi output-stream start.
Neither f_midi_disable() nor f_midi_unbind() cancels midi->work. f_midi_disable() only disables the endpoints and drains the in_req_fifo; it does not synchronize the work item, and the sound card is released asynchronously to the final free of the midi object.
The midi object is reference-counted (midi->free_ref) and is freed in f_midi_free() only once both the usb_function reference and the rawmidi private_data reference have been dropped. In f_midi_unbind(), f_midi_disable() runs before the sound card is released, so while the USB endpoints are already disabled the rawmidi device is still usable by an open substream. A concurrent userspace write on such a substream can reach f_midi_in_trigger() and queue midi->work again after f_midi_disable() has returned. A work item armed this way may still be pending when the last reference drops and f_midi_free() proceeds to kfree(midi), letting f_midi_in_work() dereference the struct after it has been freed, a use-after-free.
For this reason cancelling midi->work in f_midi_disable() would not be
sufficient: the ALSA trigger path can rearm the work after disable() returns. Cancelling at the refcount-zero free site is the boundary after which neither arming source can survive, because by then both references that keep the midi object alive have been dropped: the USB endpoints are already disabled and the rawmidi device has been released.
Fix this by calling cancel_work_sync(&midi->work) in the refcount-zero block of f_midi_free(), before the embedded work_struct is freed along with the rest of the structure. opts->lock is a sleeping mutex, so calling cancel_work_sync() under it is permitted, and the handler takes midi->transmit_lock rather than opts->lock, so no self-deadlock can occur while it waits for a running instance of the work to finish.
This issue was found by an in-house static analysis tool.
--- drivers/usb/gadget/function/f_midi.c | 1 + 1 file changed, 1 insertion(+)
drivers/usb/gadget/function/f_midi.c +1 -0
@@ -1309,6 +1309,7 @@ static void f_midi_free(struct usb_funct opts = container_of(f->fi, struct f_midi_opts, func_inst);mutex_lock (&opts->lock);if (!--midi->free_ref) { +cancel_work_sync (&midi->work);kfree (midi->id);kfifo_free (&midi->in_req_fifo);kfree (midi);
Greg Kroah-Hartman
maintainerPATCH 145/744 usb: gadget: printer: fix infinite loop in printer_read()
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Melbin K Mathew <[email protected]>
commit c2e819be6a5c7f34344926b4bd7e3dfca58cf48a upstream.
printer_read() uses the same variable for the requested copy size and the number of bytes actually copied to user space. copy_to_user() returns the number of bytes not copied, so when it fails to copy anything, the computed copied length becomes zero.
In that case len, buf, current_rx_bytes and current_rx_buf are left unchanged. If RX data is available and the user buffer remains unwritable, the read loop can repeat indefinitely.
Track the copied length separately and return -EFAULT, or the number of bytes already copied, if an iteration makes no progress.
--- drivers/usb/gadget/function/f_printer.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-)
drivers/usb/gadget/function/f_printer.c +18 -5
@@ -431,7 +431,7 @@ printer_read(struct file *fd, char __use {struct printer_dev *dev = fd->private_data;unsigned long flags; -size_t size; +size_t size, not_copied, copied;size_t bytes_copied;struct usb_request *req;/* This is a pointer to the current USB rx request. */
@@ -524,10 +524,12 @@ printer_read(struct file *fd, char __useelse size = len; - size -=copy_to_user (buf, current_rx_buf, size); - bytes_copied += size; - len -= size; - buf += size; + not_copied =copy_to_user (buf, current_rx_buf, size); + copied = size - not_copied; + + bytes_copied += copied; + len -= copied; + buf += copied;spin_lock_irqsave (&dev->lock, flags);
@@ -542,6 +544,17 @@ printer_read(struct file *fd, char __useif (dev->interface <0 ) goto out_disabled; +if (!copied) { + dev->current_rx_req = current_rx_req; + dev->current_rx_bytes = current_rx_bytes; + dev->current_rx_buf = current_rx_buf; +spin_unlock_irqrestore (&dev->lock, flags); +mutex_unlock (&dev->lock_printer_io); +return bytes_copied ? bytes_copied : -EFAULT ; + } + + size = copied; +/* If we not returning all the data left in this RX request * buffer then adjust the amount of data left in the buffer. * Othewise if we are done with this RX request buffer then
Greg Kroah-Hartman
maintainerPATCH 146/744 USB: gadget: snps-udc: fix device name leak on probe failure
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit 29a142d3e8b35ebc9e0bcc78f4bc26c9b6a9ac0b upstream.
The gadget device name is set by UDC core when registering the gadget and must not be set before to avoid leaking the name in intermediate error paths (e.g. when detecting an older chip revision).
--- drivers/usb/gadget/udc/snps_udc_core.c | 1 - 1 file changed, 1 deletion(-)
drivers/usb/gadget/udc/snps_udc_core.c +0 -1
@@ -3133,7 +3133,6 @@ int udc_probe(struct udc *dev)/* device struct setup */ dev->gadget.ops = &udc_ops; -dev_set_name (&dev->gadget.dev,"gadget" ); dev->gadget.name = name; dev->gadget.max_speed =USB_SPEED_HIGH ;
Greg Kroah-Hartman
maintainerPATCH 147/744 USB: gadget: fsl-udc: fix device name leak on probe failure
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit 6b874d00c466e73c6448a89856407fe46b2f50e4 upstream.
The gadget device name is set by UDC core when registering the gadget and must not be set before to avoid leaking the name in intermediate error paths (e.g. on dma pool creation failure).
--- drivers/usb/gadget/udc/fsl_udc_core.c | 1 - 1 file changed, 1 deletion(-)
drivers/usb/gadget/udc/fsl_udc_core.c +0 -1
@@ -2474,7 +2474,6 @@ static int fsl_udc_probe(struct platform udc_controller->gadget.name = driver_name;/* Setup gadget.dev and register with kernel */ -dev_set_name (&udc_controller->gadget.dev,"gadget" ); udc_controller->gadget.dev.of_node = pdev->dev.of_node;if (!IS_ERR_OR_NULL (udc_controller->transceiver))
Greg Kroah-Hartman
maintainerPATCH 148/744 USB: gadget: fsl-udc: fix dev_printk() device
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit c4dd150fceab281496acb3a643ae712aacb74864 upstream.
A change replacing custom printk() macros with dev_printk() incorrectly used the gadget struct device instead of the controller struct device (including for messages printed before the gadget device name has been initialised).
Switch to using the controller platform device with dev_printk() so that the controller device and driver names are included in log messages as expected.
--- drivers/usb/gadget/udc/fsl_udc_core.c | 92 +++++++++++++++------------------- drivers/usb/gadget/udc/fsl_usb2_udc.h | 1 2 files changed, 43 insertions(+), 50 deletions(-)
drivers/usb/gadget/udc/fsl_udc_core.c +42 -50
@@ -184,7 +184,7 @@ __acquires(ep->udc->lock)usb_gadget_unmap_request (&ep->udc->gadget, &req->req,ep_is_in (ep));if (status && (status != -ESHUTDOWN )) -dev_vdbg (&udc->gadget.dev,"complete %s req %p stat %d len %u/%u\n" , +dev_vdbg (udc->dev,"complete %s req %p stat %d len %u/%u\n" , ep->ep.name, &req->req, status, req->req.actual, req->req.length);
@@ -286,7 +286,7 @@ static int dr_controller_setup(struct fs timeout = jiffies +FSL_UDC_RESET_TIMEOUT ;while (fsl_readl (&dr_regs->usbcmd) &USB_CMD_CTRL_RESET ) {if (time_after (jiffies, timeout)) { -dev_err (&udc->gadget.dev,"udc reset timeout!\n" ); +dev_err (udc->dev,"udc reset timeout!\n" );return -ETIMEDOUT ; }cpu_relax ();
@@ -309,7 +309,7 @@ static int dr_controller_setup(struct fs tmp &=USB_EP_LIST_ADDRESS_MASK ;fsl_writel (tmp, &dr_regs->endpointlistaddr); -dev_vdbg (&udc->gadget.dev, +dev_vdbg (udc->dev,"vir[qh_base] is %p phy[qh_base] is 0x%8x reg is 0x%8x\n" , udc->ep_qh, (int )tmp,fsl_readl (&dr_regs->endpointlistaddr));
@@ -500,7 +500,7 @@ static void struct_ep_qh_setup(struct fs tmp = max_pkt_len <<EP_QUEUE_HEAD_MAX_PKT_LEN_POS ;break ;default : -dev_vdbg (&udc->gadget.dev,"error ep type is %d\n" , ep_type); +dev_vdbg (udc->dev,"error ep type is %d\n" , ep_type);return ; }if (zlt)
@@ -613,7 +613,7 @@ static int fsl_ep_enable(struct usb_ep *spin_unlock_irqrestore (&udc->lock, flags); retval =0 ; -dev_vdbg (&udc->gadget.dev,"enabled %s (ep%d%s) maxpacket %d\n" , +dev_vdbg (udc->dev,"enabled %s (ep%d%s) maxpacket %d\n" , ep->ep.name, ep->ep.desc->bEndpointAddress &0x0f , (desc->bEndpointAddress &USB_DIR_IN ) ?"in" :"out" , max);
@@ -634,13 +634,8 @@ static int fsl_ep_disable(struct usb_epint ep_num; ep = container_of(_ep, struct fsl_ep, ep); -if (!_ep || !ep->ep.desc) { -/* -* dev_vdbg(&udc->gadget.dev, "%s not enabled\n", -* _ep ? ep->ep.name : NULL); -*/ +if (!_ep || !ep->ep.desc)return -EINVAL ; - }/* disable ep on controller */ ep_num =ep_index (ep);
@@ -664,7 +659,7 @@ static int fsl_ep_disable(struct usb_ep ep->stopped =1 ;spin_unlock_irqrestore (&udc->lock, flags); -dev_vdbg (&udc->gadget.dev,"disabled %s OK\n" , _ep->name); +dev_vdbg (udc->dev,"disabled %s OK\n" , _ep->name);return 0 ; }
@@ -724,9 +719,6 @@ static void fsl_queue_td(struct fsl_ep * {u32 temp, bitmask, tmp_stat; -/* dev_vdbg(&udc->gadget.dev, "QH addr Register 0x%8x\n", dr_regs->endpointlistaddr); -dev_vdbg(&udc->gadget.dev, "ep_qh[%d] addr is 0x%8x\n", i, (u32)&(ep->udc->ep_qh[i])); */ - bitmask =ep_is_in (ep) ? (1 << (ep_index (ep) +16 )) : (1 << (ep_index (ep)));
@@ -813,7 +805,7 @@ static struct ep_td_struct *fsl_build_dt *is_last =0 ;if ((*is_last) ==0 ) -dev_vdbg (&udc_controller->gadget.dev,"multi-dtd request!\n" ); +dev_vdbg (udc_controller->dev,"multi-dtd request!\n" );/* Fill in the transfer size; set active bit */ swap_temp = ((*length <<DTD_LENGTH_BIT_POS ) |DTD_STATUS_ACTIVE );
@@ -825,7 +817,7 @@ static struct ep_td_struct *fsl_build_dtmb (); -dev_vdbg (&udc_controller->gadget.dev,"length = %d address= 0x%x\n" , *length, (int )*dma); +dev_vdbg (udc_controller->dev,"length = %d address= 0x%x\n" , *length, (int )*dma);return dtd; }
@@ -876,11 +868,11 @@ fsl_ep_queue(struct usb_ep *_ep, struct/* catch various bogus parameters */ if (!_req || !req->req.complete || !req->req.buf || !list_empty (&req->queue)) { -dev_vdbg (&udc->gadget.dev,"%s, bad params\n" , __func__); +dev_vdbg (udc->dev,"%s, bad params\n" , __func__);return -EINVAL ; }if (unlikely (!ep->ep.desc)) { -dev_vdbg (&udc->gadget.dev,"%s, bad ep\n" , __func__); +dev_vdbg (udc->dev,"%s, bad ep\n" , __func__);return -EINVAL ; }if (usb_endpoint_xfer_isoc (ep->ep.desc)) {
@@ -1040,7 +1032,7 @@ static int fsl_ep_set_halt(struct usb_ep udc->ep0_dir =0 ; } out: -dev_vdbg (&udc->gadget.dev,"%s %s halt stat %d\n" , ep->ep.name, +dev_vdbg (udc->dev,"%s %s halt stat %d\n" , ep->ep.name, value ?"set" :"clear" , status);return status;
@@ -1109,7 +1101,7 @@ static void fsl_ep_fifo_flush(struct usb/* Wait until flush complete */ while (fsl_readl (&dr_regs->endptflush)) {if (time_after (jiffies, timeout)) { -dev_err (&udc_controller->gadget.dev, +dev_err (udc_controller->dev,"ep flush timeout\n" );return ; }
@@ -1182,7 +1174,7 @@ static int fsl_vbus_session(struct usb_g udc = container_of(gadget, struct fsl_udc, gadget);spin_lock_irqsave (&udc->lock, flags); -dev_vdbg (&gadget->dev,"VBUS %s\n" ,str_on_off (is_active)); +dev_vdbg (udc->dev,"VBUS %s\n" ,str_on_off (is_active)); udc->vbus_active = (is_active !=0 );if (can_pullup (udc)) fsl_writel((fsl_readl(&dr_regs->usbcmd) | USB_CMD_RUN_STOP),
@@ -1548,7 +1540,7 @@ static void ep0_req_complete(struct fsl_ udc->ep0_state =WAIT_FOR_SETUP ;break ;case WAIT_FOR_SETUP : -dev_err (&udc->gadget.dev,"Unexpected ep0 packets\n" ); +dev_err (udc->dev,"Unexpected ep0 packets\n" );break ;default :ep0stall (udc);
@@ -1617,7 +1609,7 @@ static int process_ep_req(struct fsl_udc errors =hc32_to_cpu (curr_td->size_ioc_sts);if (errors &DTD_ERROR_MASK ) {if (errors &DTD_STATUS_HALTED ) { -dev_err (&udc->gadget.dev,"dTD error %08x QH=%d\n" , errors, pipe); +dev_err (udc->dev,"dTD error %08x QH=%d\n" , errors, pipe);/* Clear the errors and Halt condition */ tmp =hc32_to_cpu (curr_qh->size_ioc_int_sts); tmp &= ~errors;
@@ -1628,26 +1620,26 @@ static int process_ep_req(struct fsl_udcbreak ; }if (errors &DTD_STATUS_DATA_BUFF_ERR ) { -dev_vdbg (&udc->gadget.dev,"Transfer overflow\n" ); +dev_vdbg (udc->dev,"Transfer overflow\n" ); status = -EPROTO ;break ; }else if (errors &DTD_STATUS_TRANSACTION_ERR ) { -dev_vdbg (&udc->gadget.dev,"ISO error\n" ); +dev_vdbg (udc->dev,"ISO error\n" ); status = -EILSEQ ;break ; }else -dev_err (&udc->gadget.dev, +dev_err (udc->dev,"Unknown error has occurred (0x%x)!\n" , errors); }else if (hc32_to_cpu (curr_td->size_ioc_sts) &DTD_STATUS_ACTIVE ) { -dev_vdbg (&udc->gadget.dev,"Request not complete\n" ); +dev_vdbg (udc->dev,"Request not complete\n" ); status =REQ_UNCOMPLETE ;return status; }else if (remaining_length) {if (direction) { -dev_vdbg (&udc->gadget.dev, +dev_vdbg (udc->dev,"Transmit dTD remaining length not zero\n" ); status = -EPROTO ;break ;
@@ -1655,8 +1647,7 @@ static int process_ep_req(struct fsl_udcbreak ; } }else { -dev_vdbg (&udc->gadget.dev, -"dTD transmitted successful\n" ); +dev_vdbg (udc->dev,"dTD transmitted successful\n" ); }if (j != curr_req->dtd_count -1 )
@@ -1699,7 +1690,7 @@ static void dtd_complete_irq(struct fsl_/* If the ep is configured */ if (!curr_ep->ep.name) { -dev_warn (&udc->gadget.dev,"Invalid EP?\n" ); +dev_warn (udc->dev,"Invalid EP?\n" );continue ; }
@@ -1708,7 +1699,7 @@ static void dtd_complete_irq(struct fsl_ queue) { status =process_ep_req (udc, i, curr_req); -dev_vdbg (&udc->gadget.dev, +dev_vdbg (udc->dev,"status of process_ep_req= %d, ep = %d\n" , status, ep_num);if (status ==REQ_UNCOMPLETE )
@@ -1829,7 +1820,7 @@ static void reset_irq(struct fsl_udc *udwhile (fsl_readl (&dr_regs->endpointprime)) {/* Wait until all endptprime bits cleared */ if (time_after (jiffies, timeout)) { -dev_err (&udc->gadget.dev,"Timeout for reset\n" ); +dev_err (udc->dev,"Timeout for reset\n" );break ; }cpu_relax ();
@@ -1839,7 +1830,7 @@ static void reset_irq(struct fsl_udc *udfsl_writel (0xffffffff , &dr_regs->endptflush);if (fsl_readl (&dr_regs->portsc1) &PORTSCX_PORT_RESET ) { -dev_vdbg (&udc->gadget.dev,"Bus reset\n" ); +dev_vdbg (udc->dev,"Bus reset\n" );/* Bus is reseting */ udc->bus_reset =1 ;/* Reset all the queues, include XD, dTD, EP queue
@@ -1847,7 +1838,7 @@ static void reset_irq(struct fsl_udc *udreset_queues (udc, true); udc->usb_state =USB_STATE_DEFAULT ; }else { -dev_vdbg (&udc->gadget.dev,"Controller reset\n" ); +dev_vdbg (udc->dev,"Controller reset\n" );/* initialize usb hw reg except for regs for EP, not * touch usbintr reg */ dr_controller_setup (udc);
@@ -1881,7 +1872,7 @@ static irqreturn_t fsl_udc_irq(int irq,/* Clear notification bits */ fsl_writel (irq_src, &dr_regs->usbsts); -/* dev_vdbg(&udc->gadget.dev, "irq_src [0x%8x]", irq_src); */ +/* dev_vdbg(udc->dev, "irq_src [0x%8x]", irq_src); */ /* Need to resume? */ if (udc->usb_state ==USB_STATE_SUSPENDED )
@@ -1890,7 +1881,7 @@ static irqreturn_t fsl_udc_irq(int irq,/* USB Interrupt */ if (irq_src &USB_STS_INT ) { -dev_vdbg (&udc->gadget.dev,"Packet int\n" ); +dev_vdbg (udc->dev,"Packet int\n" );/* Setup package, we only support ep0 as control ep */ if (fsl_readl (&dr_regs->endptsetupstat) &EP_SETUP_STATUS_EP0 ) { tripwire_handler(udc, 0,
@@ -1919,7 +1910,7 @@ static irqreturn_t fsl_udc_irq(int irq,/* Reset Received */ if (irq_src &USB_STS_RESET ) { -dev_vdbg (&udc->gadget.dev,"reset int\n" ); +dev_vdbg (udc->dev,"reset int\n" );reset_irq (udc); status =IRQ_HANDLED ; }
@@ -1931,7 +1922,7 @@ static irqreturn_t fsl_udc_irq(int irq, }if (irq_src & (USB_STS_ERR |USB_STS_SYS_ERR )) { -dev_vdbg (&udc->gadget.dev,"Error IRQ %x\n" , irq_src); +dev_vdbg (udc->dev,"Error IRQ %x\n" , irq_src); }spin_unlock_irqrestore (&udc->lock, flags);
@@ -1967,7 +1958,7 @@ static int fsl_udc_start(struct usb_gadg udc_controller->transceiver->otg, &udc_controller->gadget);if (retval <0 ) { -dev_err (&udc_controller->gadget.dev,"can't bind to transceiver\n" ); +dev_err (udc_controller->dev,"can't bind to transceiver\n" ); udc_controller->driver =NULL ;return retval; }
@@ -2252,7 +2243,7 @@ static int struct_udc_setup(struct fsl_u udc->eps = kzalloc_objs(struct fsl_ep, udc->max_ep);if (!udc->eps) { -dev_err (&udc->gadget.dev,"kmalloc udc endpoint status failed\n" ); +dev_err (udc->dev,"kmalloc udc endpoint status failed\n" ); goto eps_alloc_failed; }
@@ -2267,7 +2258,7 @@ static int struct_udc_setup(struct fsl_u udc->ep_qh =dma_alloc_coherent (&pdev->dev, size, &udc->ep_qh_dma,GFP_KERNEL );if (!udc->ep_qh) { -dev_err (&udc->gadget.dev,"malloc QHs for udc failed\n" ); +dev_err (udc->dev,"malloc QHs for udc failed\n" ); goto ep_queue_alloc_failed; }
@@ -2278,14 +2269,14 @@ static int struct_udc_setup(struct fsl_u udc->status_req =container_of (fsl_alloc_request (NULL ,GFP_KERNEL ), struct fsl_req, req);if (!udc->status_req) { -dev_err (&udc->gadget.dev,"kzalloc for udc status request failed\n" ); +dev_err (udc->dev,"kzalloc for udc status request failed\n" ); goto udc_status_alloc_failed; }/* allocate a small amount of memory to get valid address */ udc->status_req->req.buf =kmalloc (8 ,GFP_KERNEL );if (!udc->status_req->req.buf) { -dev_err (&udc->gadget.dev,"kzalloc for udc request buffer failed\n" ); +dev_err (udc->dev,"kzalloc for udc request buffer failed\n" ); goto udc_req_buf_alloc_failed; }
@@ -2373,6 +2364,7 @@ static int fsl_udc_probe(struct platformif (udc_controller ==NULL )return -ENOMEM ; + udc_controller->dev = &pdev->dev; pdata =dev_get_platdata (&pdev->dev); udc_controller->pdata = pdata;spin_lock_init (&udc_controller->lock);
@@ -2382,7 +2374,7 @@ static int fsl_udc_probe(struct platformif (pdata->operating_mode ==FSL_USB2_DR_OTG ) { udc_controller->transceiver =usb_get_phy (USB_PHY_TYPE_USB2 );if (IS_ERR_OR_NULL (udc_controller->transceiver)) { -dev_err (&udc_controller->gadget.dev,"Can't find OTG driver!\n" ); +dev_err (&pdev->dev,"Can't find OTG driver!\n" ); ret = -ENODEV ; goto err_kfree; }
@@ -2398,7 +2390,7 @@ static int fsl_udc_probe(struct platformif (pdata->operating_mode ==FSL_USB2_DR_DEVICE ) {if (!request_mem_region (res->start,resource_size (res), driver_name)) { -dev_err (&udc_controller->gadget.dev,"request mem region for %s failed\n" , pdev->name); +dev_err (&pdev->dev,"failed to request mem region\n" ); ret = -EBUSY ; goto err_kfree; }
@@ -2429,7 +2421,7 @@ static int fsl_udc_probe(struct platform/* Read Device Controller Capability Parameters register */ dccparams =fsl_readl (&dr_regs->dccparams);if (!(dccparams &DCCPARAMS_DC )) { -dev_err (&udc_controller->gadget.dev,"This SOC doesn't support device role\n" ); +dev_err (&pdev->dev,"This SOC doesn't support device role\n" ); ret = -ENODEV ; goto err_exit; }
@@ -2447,14 +2439,14 @@ static int fsl_udc_probe(struct platform ret =request_irq (udc_controller->irq, fsl_udc_irq,IRQF_SHARED , driver_name, udc_controller);if (ret !=0 ) { -dev_err (&udc_controller->gadget.dev,"cannot request irq %d err %d\n" , +dev_err (&pdev->dev,"cannot request irq %d err %d\n" , udc_controller->irq, ret); goto err_exit; }/* Initialize the udc structure including QH member and other member */ if (struct_udc_setup (udc_controller, pdev)) { -dev_err (&udc_controller->gadget.dev,"Can't initialize udc data structure\n" ); +dev_err (&pdev->dev,"Can't initialize udc data structure\n" ); ret = -ENOMEM ; goto err_free_irq; }
drivers/usb/gadget/udc/fsl_usb2_udc.h +1 -0
@@ -470,6 +470,7 @@ struct fsl_ep {#define EP_DIR_OUT 0struct fsl_udc { +struct device *dev;struct usb_gadget gadget;struct usb_gadget_driver *driver;struct fsl_usb2_platform_data *pdata;
Greg Kroah-Hartman
maintainerPATCH 149/744 usb: gadget: f_ncm: validate datagram bounds in ncm_unwrap_ntb()
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sonali Pradhan <[email protected]>
commit 1febec7e47cdcd01f43fb0211094e3010474666e upstream.
When unpacking host-supplied NTBs, ncm_unwrap_ntb() checks datagram length against frame_max but does not verify that the datagram fits within the declared block length. Additionally, when decoding multiple NTBs from a single socket buffer, subsequent block lengths are not checked against the actual remaining buffer data.
With these checks missing, a malicious USB host can specify datagram offsets and lengths that point beyond the block, or supply secondary NTB headers declaring lengths larger than the buffer. skb_put_data() then copies adjacent kernel memory from skb_shared_info into the network skb.
Fix this by verifying that sufficient buffer space remains for the NTB header before parsing, handling zero-length block declarations, ensuring that block lengths never exceed the remaining buffer space, and verifying that each datagram payload stays strictly within the block boundary.
--- drivers/usb/gadget/function/f_ncm.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-)
drivers/usb/gadget/function/f_ncm.c +13 -4
@@ -1189,6 +1189,10 @@ static int ncm_unwrap_ntb(struct gether frame_max = ncm_opts->max_segment_size; parse_ntb: +if (to_process < (int )opts->nth_size) { +INFO (port->func.config->cdev,"Packet too small for headers\n" ); + goto err; + } tmp = (__le16 *)ntb_ptr;/* dwSignature */
@@ -1209,8 +1213,12 @@ parse_ntb: tmp++;/* skip wSequence */ block_len =get_ncm (&tmp, opts->block_length); +if (block_len ==0 ) + block_len = to_process; +/* (d)wBlockLength */ -if ((block_len < opts->nth_size + opts->ndp_size) || (block_len > ntb_max)) { +if ((block_len < opts->nth_size + opts->ndp_size) || (block_len > ntb_max) || + (block_len > to_process)) {INFO (port->func.config->cdev,"Bad block length: %#X\n" , block_len); goto err; }
@@ -1273,7 +1281,7 @@ parse_ntb: index = index2;/* wDatagramIndex[0] */ if ((index < opts->nth_size) || - (index > block_len - opts->dpe_size)) { + (index > block_len)) {INFO (port->func.config->cdev,"Bad index: %#X\n" , index); goto err;
@@ -1285,7 +1293,8 @@ parse_ntb:* ethernet hdr + crc or larger than max frame size */ if ((dg_len <14 + crc_len) || - (dg_len > frame_max)) { + (dg_len > frame_max) || + (dg_len > block_len - index)) {INFO (port->func.config->cdev,"Bad dgram length: %#X\n" , dg_len); goto err;
@@ -1310,7 +1319,7 @@ parse_ntb: dg_len2 =get_ncm (&tmp, opts->dgram_item_len);/* wDatagramIndex[1] */ -if (index2 > block_len - opts->dpe_size) { +if (index2 > block_len) {INFO (port->func.config->cdev,"Bad index: %#X\n" , index2); goto err;
Greg Kroah-Hartman
maintainerPATCH 150/744 usb: gadget: f_tcm: synchronize delayed set_alt with teardown
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cen Zhang <[email protected]>
commit 79e2d75725c85607f8a9d87ae9cace62a19f767d upstream.
The f_tcm set_alt() path defers endpoint setup to a work item and completes the delayed status response from process context. The delayed work uses f_tcm private state and may complete the setup request after disconnect or function teardown has already moved on.
Cancel and drain the delayed set_alt work when the function is unbound or freed. For disable paths, which are reached under the composite device lock, use a small state machine and a non-sleeping cancellation path instead of cancel_work_sync(). If the work is already running, mark it cancelled and let the worker own the cleanup; otherwise tcm_disable() can cancel the queued work and clean up immediately.
Also serialize the final delayed-status completion with the cancellation check while holding the composite device lock. This prevents a disconnect from clearing delayed_status while the worker is about to complete the control request.
Validation reproduced this kernel report:
BUG: KASAN: slab-use-after-free in tcm_delayed_set_alt+0x6c/0xef0 Call Trace: <TASK> dump_stack_lvl+0x66/0xa0 print_report+0xce/0x630 ? tcm_delayed_set_alt+0x6c/0xef0 ? srso_alias_return_thunk+0x5/0xfbef5 ? __virt_addr_valid+0x188/0x320 ? tcm_delayed_set_alt+0x6c/0xef0 kasan_report+0xe0/0x110 ? tcm_delayed_set_alt+0x6c/0xef0 tcm_delayed_set_alt+0x6c/0xef0 ? __pfx_tcm_delayed_set_alt+0x10/0x10 ? process_one_work+0x4cb/0xb90 ? rcu_is_watching+0x20/0x50 ? tcm_delayed_set_alt+0x9/0xef0 process_one_work+0x4d7/0xb90 ? __pfx_process_one_work+0x10/0x10 ? srso_alias_return_thunk+0x5/0xfbef5 ? __list_add_valid_or_report+0x37/0xf0 ? __pfx_tcm_delayed_set_alt+0x10/0x10 ? srso_alias_return_thunk+0x5/0xfbef5 worker_thread+0x2d8/0x570 ? __pfx_worker_thread+0x10/0x10 kthread+0x1ad/0x1f0 ? __pfx_kthread+0x10/0x10 ret_from_fork+0x3c9/0x540 ? __pfx_ret_from_fork+0x10/0x10 ? srso_alias_return_thunk+0x5/0xfbef5 ? __switch_to+0x2e9/0x730 ? __pfx_kthread+0x10/0x10 ret_from_fork_asm+0x1a/0x30 </TASK> Allocated by task 544: kasan_save_stack+0x33/0x60 kasan_save_track+0x14/0x30 __kasan_kmalloc+0x8f/0xa0 tcm_alloc+0x68/0x180 usb_get_function+0x36/0x60 config_usb_cfg_link+0x125/0x1b0 configfs_symlink+0x322/0x890 vfs_symlink+0xc2/0x270 filename_symlinkat+0x295/0x2f0 __x64_sys_symlinkat+0x62/0x90 do_syscall_64+0x115/0x6a0 entry_SYSCALL_64_after_hwframe+0x77/0x7f Freed by task 661: kasan_save_stack+0x33/0x60 kasan_save_track+0x14/0x30 kasan_save_free_info+0x3b/0x60 __kasan_slab_free+0x43/0x70 kfree+0x2f9/0x530 config_usb_cfg_unlink+0x173/0x1e0 configfs_unlink+0x1fa/0x340 vfs_unlink+0x15c/0x510 filename_unlinkat+0x2ba/0x450 __x64_sys_unlinkat+0x63/0x90 do_syscall_64+0x115/0x6a0 entry_SYSCALL_64_after_hwframe+0x77/0x7f
--- drivers/usb/gadget/function/f_tcm.c | 192 ++++++++++++++++++++++++++++++------ drivers/usb/gadget/function/tcm.h | 13 ++ 2 files changed, 177 insertions(+), 28 deletions(-)
drivers/usb/gadget/function/f_tcm.c +164 -28
@@ -2363,31 +2363,158 @@ ep_fail:return -ENOTSUPP ; } -struct guas_setup_wq { -struct work_struct work; -struct f_uas *fu; -unsigned int alt; -}; +static void tcm_cleanup_old_alt (struct f_uas *fu) +{ +if (fu->flags &USBG_IS_UAS ) +uasp_cleanup_old_alt (fu); +else if (fu->flags &USBG_IS_BOT ) +bot_cleanup_old_alt (fu); + fu->flags =0 ; +} + +static void tcm_delayed_set_alt_done (struct f_uas *fu) +{ +unsigned long flags; + +spin_lock_irqsave (&fu->delayed_set_alt_lock, flags); + fu->delayed_set_alt_state =USBG_DELAYED_SET_ALT_IDLE ; + fu->delayed_set_alt_cancel = false; +spin_unlock_irqrestore (&fu->delayed_set_alt_lock, flags); +} + +static bool tcm_delayed_set_alt_cancelled (struct f_uas *fu) +{ +bool cancelled; +unsigned long flags; + +spin_lock_irqsave (&fu->delayed_set_alt_lock, flags); + cancelled = fu->delayed_set_alt_cancel; +spin_unlock_irqrestore (&fu->delayed_set_alt_lock, flags); + +return cancelled; +} + +static bool tcm_complete_delayed_status (struct f_uas *fu) +{ +struct usb_composite_dev *cdev = fu->function.config->cdev; +struct usb_request *req = cdev->req; +unsigned long cdev_flags; +bool cancelled; +int ret; + +spin_lock_irqsave (&cdev->lock, cdev_flags); +spin_lock (&fu->delayed_set_alt_lock); + cancelled = fu->delayed_set_alt_cancel; +if (!cancelled) { + fu->delayed_set_alt_state =USBG_DELAYED_SET_ALT_IDLE ; + fu->delayed_set_alt_cancel = false; + } +spin_unlock (&fu->delayed_set_alt_lock); + +if (cancelled) { +spin_unlock_irqrestore (&cdev->lock, cdev_flags); +return false; + } + +if (cdev->delayed_status ==0 ) { +WARN (cdev,"%s: Unexpected call\n" , __func__); + }else if (--cdev->delayed_status ==0 ) { + req->length =0 ; + req->context = cdev; + ret =usb_ep_queue (cdev->gadget->ep0, req,GFP_ATOMIC ); +if (ret ==0 ) { + cdev->setup_pending = true; + }else { + req->status =0 ; + req->complete (cdev->gadget->ep0, req); + } + } + +spin_unlock_irqrestore (&cdev->lock, cdev_flags); + +return true; +} + +static bool tcm_cancel_delayed_set_alt (struct f_uas *fu) +{ +bool cleanup = false; +bool cancel = false; +unsigned long flags; + +spin_lock_irqsave (&fu->delayed_set_alt_lock, flags); +switch (fu->delayed_set_alt_state) { +case USBG_DELAYED_SET_ALT_IDLE : + cleanup = true; +break ; +case USBG_DELAYED_SET_ALT_QUEUED : +case USBG_DELAYED_SET_ALT_RUNNING : + fu->delayed_set_alt_cancel = true; + cancel = true; +break ; + } +spin_unlock_irqrestore (&fu->delayed_set_alt_lock, flags); + +if (cancel &&cancel_work (&fu->delayed_set_alt)) { +spin_lock_irqsave (&fu->delayed_set_alt_lock, flags); +if (fu->delayed_set_alt_state ==USBG_DELAYED_SET_ALT_QUEUED ) { + fu->delayed_set_alt_state =USBG_DELAYED_SET_ALT_IDLE ; + fu->delayed_set_alt_cancel = false; + cleanup = true; + } +spin_unlock_irqrestore (&fu->delayed_set_alt_lock, flags); + } + +return cleanup; +} + +static void tcm_cancel_delayed_set_alt_sync (struct f_uas *fu) +{ +unsigned long flags; + +spin_lock_irqsave (&fu->delayed_set_alt_lock, flags); +if (fu->delayed_set_alt_state !=USBG_DELAYED_SET_ALT_IDLE ) + fu->delayed_set_alt_cancel = true; +spin_unlock_irqrestore (&fu->delayed_set_alt_lock, flags); + +cancel_work_sync (&fu->delayed_set_alt); + +spin_lock_irqsave (&fu->delayed_set_alt_lock, flags); + fu->delayed_set_alt_state =USBG_DELAYED_SET_ALT_IDLE ; + fu->delayed_set_alt_cancel = false; +spin_unlock_irqrestore (&fu->delayed_set_alt_lock, flags); +}static void tcm_delayed_set_alt (struct work_struct *wq) { - struct guas_setup_wq *work = container_of(wq, struct guas_setup_wq, - work); -struct f_uas *fu = work->fu; -int alt = work->alt; + struct f_uas *fu = container_of(wq, struct f_uas, delayed_set_alt); +unsigned long flags; +unsigned int alt; + +spin_lock_irqsave (&fu->delayed_set_alt_lock, flags); +if (fu->delayed_set_alt_state !=USBG_DELAYED_SET_ALT_QUEUED ) { +spin_unlock_irqrestore (&fu->delayed_set_alt_lock, flags); +return ; + } + fu->delayed_set_alt_state =USBG_DELAYED_SET_ALT_RUNNING ; + alt = fu->delayed_alt; +spin_unlock_irqrestore (&fu->delayed_set_alt_lock, flags); -kfree (work); +tcm_cleanup_old_alt (fu); -if (fu->flags &USBG_IS_BOT ) -bot_cleanup_old_alt (fu); -if (fu->flags &USBG_IS_UAS ) -uasp_cleanup_old_alt (fu); +if (tcm_delayed_set_alt_cancelled (fu)) + goto out_done;if (alt ==USB_G_ALT_INT_BBB )bot_set_alt (fu);else if (alt ==USB_G_ALT_INT_UAS )uasp_set_alt (fu); -usb_composite_setup_continue (fu->function.config->cdev); + +if (tcm_complete_delayed_status (fu)) +return ; + +tcm_cleanup_old_alt (fu); +out_done: +tcm_delayed_set_alt_done (fu); }static int tcm_get_alt (struct usb_function *f,unsigned intf)
@@ -2413,15 +2540,20 @@ static int tcm_set_alt(struct usb_functireturn -EOPNOTSUPP ;if ((alt ==USB_G_ALT_INT_BBB ) || (alt ==USB_G_ALT_INT_UAS )) { -struct guas_setup_wq *work; +unsigned long flags; + +spin_lock_irqsave (&fu->delayed_set_alt_lock, flags); +if (fu->delayed_set_alt_state !=USBG_DELAYED_SET_ALT_IDLE ) { +spin_unlock_irqrestore (&fu->delayed_set_alt_lock, + flags); +return -EBUSY ; + } + fu->delayed_alt = alt; + fu->delayed_set_alt_cancel = false; + fu->delayed_set_alt_state =USBG_DELAYED_SET_ALT_QUEUED ; +spin_unlock_irqrestore (&fu->delayed_set_alt_lock, flags); - work =kmalloc_obj (*work,GFP_ATOMIC ); -if (!work) -return -ENOMEM ; -INIT_WORK (&work->work, tcm_delayed_set_alt); - work->fu = fu; - work->alt = alt; -schedule_work (&work->work); +schedule_work (&fu->delayed_set_alt);return USB_GADGET_DELAYED_STATUS ; }return -EOPNOTSUPP ;
@@ -2431,11 +2563,8 @@ static void tcm_disable(struct usb_funct {struct f_uas *fu =to_f_uas (f); -if (fu->flags &USBG_IS_UAS ) -uasp_cleanup_old_alt (fu); -else if (fu->flags &USBG_IS_BOT ) -bot_cleanup_old_alt (fu); - fu->flags =0 ; +if (tcm_cancel_delayed_set_alt (fu)) +tcm_cleanup_old_alt (fu); } static int tcm_setup(struct usb_function *f,
@@ -2583,11 +2712,16 @@ static void tcm_free(struct usb_function {struct f_uas *tcm =to_f_uas (f); +tcm_cancel_delayed_set_alt_sync (tcm);kfree (tcm); }static void tcm_unbind (struct usb_configuration *c,struct usb_function *f) { +struct f_uas *fu =to_f_uas (f); + +tcm_cancel_delayed_set_alt_sync (fu); +tcm_cleanup_old_alt (fu);usb_free_all_descriptors (f); }
@@ -2620,6 +2754,8 @@ static struct usb_function *tcm_alloc(st fu->function.disable = tcm_disable; fu->function.free_func = tcm_free; fu->tpg = tpg_instances[i].tpg; +INIT_WORK (&fu->delayed_set_alt, tcm_delayed_set_alt); +spin_lock_init (&fu->delayed_set_alt_lock);hash_init (fu->stream_hash);mutex_unlock (&tpg_instances_lock);
drivers/usb/gadget/function/tcm.h +13 -0
@@ -3,6 +3,7 @@#define __TARGET_USB_GADGET_H__#include <linux/kref.h> +#include <linux/spinlock.h> /* #include <linux/usb/uas.h> */ #include <linux/hashtable.h> #include <linux/usb/composite.h>
@@ -29,6 +30,12 @@ enum {#define USB_G_DEFAULT_SESSION_TAGS USBG_NUM_CMDS +enum { +USBG_DELAYED_SET_ALT_IDLE =0 , +USBG_DELAYED_SET_ALT_QUEUED , +USBG_DELAYED_SET_ALT_RUNNING , +}; +struct tcm_usbg_nexus {struct se_session *tvn_se_sess; };
@@ -132,6 +139,12 @@ struct f_uas {#define USBG_BOT_CMD_PEND (1 << 4)#define USBG_BOT_WEDGED (1 << 5) +struct work_struct delayed_set_alt; +spinlock_t delayed_set_alt_lock;/* protects delayed_set_alt_* */ +unsigned int delayed_alt; +unsigned int delayed_set_alt_state; +bool delayed_set_alt_cancel; +struct usbg_cdb cmd[USBG_NUM_CMDS ];struct usb_ep *ep_in;struct usb_ep *ep_out;
Greg Kroah-Hartman
maintainerPATCH 151/744 usb: gadget: udc: bdc: free IRQ and drain func_wake_notify before teardown
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Fan Wu <[email protected]>
commit 0583f2fbf8f86ae3a0ce054f96783dd83e65d9bb upstream.
The Broadcom BDC UDC driver registers its IRQ handler with devm_request_irq() in bdc_udc_init(), so the IRQ is released by devm only after bdc_remove() returns. devm releases resources in reverse LIFO order, but bdc_remove() runs bdc_udc_exit() and bdc_hw_exit() -> bdc_mem_free() manually before returning: bdc_udc_exit() tears down individual endpoint objects via bdc_free_ep(), while bdc_hw_exit() -> bdc_mem_free() frees and NULLs the DMA-coherent status-report ring (bdc->srr.sr_bds) and kfree()s bdc->bdc_ep_array. Both happen while the IRQ handler (bdc_udc_interrupt, requested with IRQF_SHARED) remains deliverable in the window up to the post-remove devm free_irq().
On receipt of a shared interrupt in that window, bdc_udc_interrupt() dereferences bdc->srr.sr_bds[bdc->srr.dqp_index] (NULL or freed DMA) and dispatches sr_handler callbacks that index into bdc_ep_array, causing a NULL-deref or use-after-free.
The same window affects the delayed_work bdc->func_wake_notify, which is armed from the IRQ handler via bdc_sr_uspc() -> handle_link_state_change() -> schedule_delayed_work() and may self-rearm from its own callback bdc_func_wake_timer(). No cancel exists anywhere in the driver, so a queued work item that fires after bdc_remove() returns and the bdc structure is devm-freed dereferences freed memory.
Replace devm_request_irq() with request_irq() and add an explicit free_irq(bdc->irq, bdc) in bdc_remove(). Clear BDC_GIE before free_irq() to stop the device from asserting interrupts, then free_irq() drains any in-flight handler, then cancel_delayed_work_sync() drains the func_wake_notify delayed work. This ordering ensures the IRQ handler and delayed work cannot interfere with the subsequent endpoint and DMA teardown in bdc_udc_exit() and bdc_hw_exit(). Wire the matching free_irq() into the bdc_udc_init() error path so the IRQ is released on probe failure, and route the bdc_init_ep() failure through err0 instead of returning directly.
This issue was found by an in-house static analysis tool.
--- drivers/usb/gadget/udc/bdc/bdc_core.c | 20 ++++++++++++++++++++ drivers/usb/gadget/udc/bdc/bdc_udc.c | 7 ++++--- 2 files changed, 24 insertions(+), 3 deletions(-)
drivers/usb/gadget/udc/bdc/bdc_core.c +20 -0
@@ -585,9 +585,29 @@ disable_clk:static void bdc_remove (struct platform_device *pdev) {struct bdc *bdc; +unsigned long flags; +u32 temp; bdc =platform_get_drvdata (pdev);dev_dbg (bdc->dev,"%s ()\n" , __func__); +/* +* Disable the device interrupt source before freeing the IRQ: +* clear BDC_GIE so the controller stops asserting interrupts, +* then free_irq drains any in-flight handler. +*/ +spin_lock_irqsave (&bdc->lock, flags); + temp =bdc_readl (bdc->regs,BDC_BDCSC ); + temp &= ~BDC_GIE ; +bdc_writel (bdc->regs,BDC_BDCSC , temp); +spin_unlock_irqrestore (&bdc->lock, flags); +free_irq (bdc->irq, bdc); +/* +* Drain func_wake_notify after free_irq: the IRQ handler arms this +* delayed_work via bdc_sr_uspc -> handle_link_state_change -> +* schedule_delayed_work (self-rearmed in bdc_func_wake_timer), so +* the IRQ must be released first to prevent re-arm after cancel. +*/ +cancel_delayed_work_sync (&bdc->func_wake_notify);bdc_udc_exit (bdc);bdc_hw_exit (bdc);bdc_phy_exit (bdc);
drivers/usb/gadget/udc/bdc/bdc_udc.c +4 -3
@@ -530,8 +530,8 @@ int bdc_udc_init(struct bdc *bdc) bdc->gadget.name =BRCM_BDC_NAME ; - ret =devm_request_irq (bdc->dev, bdc->irq, bdc_udc_interrupt, -IRQF_SHARED ,BRCM_BDC_NAME , bdc); + ret =request_irq (bdc->irq, bdc_udc_interrupt,IRQF_SHARED , +BRCM_BDC_NAME , bdc);if (ret) { dev_err(bdc->dev, "failed to request irq #%d %d\n",
@@ -542,7 +542,7 @@ int bdc_udc_init(struct bdc *bdc) ret =bdc_init_ep (bdc);if (ret) {dev_err (bdc->dev,"bdc init ep fail: %d\n" , ret); -return ret; + goto err0; } ret =usb_add_gadget_udc (bdc->dev, &bdc->gadget);
@@ -571,6 +571,7 @@ int bdc_udc_init(struct bdc *bdc) err1:usb_del_gadget_udc (&bdc->gadget); err0: +free_irq (bdc->irq, bdc);bdc_free_ep (bdc);return ret;
Greg Kroah-Hartman
maintainerPATCH 152/744 usb: gadget: uvc: clamp SEND_RESPONSE length to the response buffer
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Muhammad Bilal <[email protected]>
commit b70dc75e85ba968b7b76eebfe5d63000080b875b upstream.
uvc_send_response() builds the UVC control response from a user-supplied struct uvc_request_data:
req->length = min_t(unsigned int, uvc->event_length, data->length); ... memcpy(req->buf, data->data, req->length);
req->length is clamped to uvc->event_length, which is taken from the host control request wLength (up to UVC_MAX_REQUEST_SIZE, 64), and to data->length, which comes from the UVCIOC_SEND_RESPONSE ioctl and is only checked for being negative. The source buffer data->data is only 60 bytes, so a response with uvc->event_length and data->length both greater than 60 makes memcpy() read past the end of data->data.
Clamp req->length to sizeof(data->data) as well.
--- drivers/usb/gadget/function/uvc_v4l2.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/usb/gadget/function/uvc_v4l2.c +2 -0
@@ -200,6 +200,8 @@ uvc_send_response(struct uvc_device *uvcreturn usb_ep_set_halt (cdev->gadget->ep0); req->length = min_t(unsigned int, uvc->event_length, data->length); +if (req->length >sizeof (data->data)) + req->length =sizeof (data->data); req->zero = data->length < uvc->event_length;memcpy (req->buf, data->data, req->length);
Greg Kroah-Hartman
maintainerPATCH 153/744 USB: serial: ftdi_sio: add support for E+H FXA291
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tim Pambor <[email protected]>
commit fad0fd120e29041b3e6cdf41bb12e3184fb524a2 upstream.
The Commubox FXA291 by Endress+Hauser AG is a USB serial converter based on FT232B which is used to communicate with field devices.
It enumerates using the FTDI vendor ID and a custom PID.
usb 1-9: New USB device found, idVendor=0403, idProduct=e510, bcdDevice= 4.00 usb 1-9: New USB device strings: Mfr=1, Product=2, SerialNumber=0 usb 1-9: Product: FXA291
usb 1-9: Manufacturer: Endress+Hauser
usb 1-9: SerialNumber: 00000000ftdi_sio 1-9:1.0: FTDI USB Serial Device converter detected
usb 1-9: Detected FT232B
usb 1-9: FTDI USB Serial Device converter now attached to ttyUSB0
--- drivers/usb/serial/ftdi_sio.c | 2 ++ drivers/usb/serial/ftdi_sio_ids.h | 5 +++++ 2 files changed, 7 insertions(+)
drivers/usb/serial/ftdi_sio.c +2 -0
@@ -1073,6 +1073,8 @@ static const struct usb_device_id id_tab { USB_DEVICE_INTERFACE_NUMBER(ALTERA_VID, ALTERA_UB3_602E_PID, 3) },/* Abacus Electrics */ { USB_DEVICE(FTDI_VID, ABACUS_OPTICAL_PROBE_PID) }, +/* Endress+Hauser AG devices */ + { USB_DEVICE(FTDI_VID, FTDI_EH_FXA291_PID) }, { } /* Terminating entry */ };
drivers/usb/serial/ftdi_sio_ids.h +5 -0
@@ -314,6 +314,11 @@#define FTDI_ELV_UIO88_PID 0xFB5F/* USB-I/O Interface (UIO 88) */ /* +* Endress+Hauser AG product ids (FTDI_VID) +*/ +#define FTDI_EH_FXA291_PID 0xE510 + +/* * EVER Eco Pro UPS (http://www.ever.com.pl/) */
Greg Kroah-Hartman
maintainerPATCH 154/744 USB: serial: io_edgeport: cap received transmit credits
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sunho Park <[email protected]>
commit faaddd811c5099f11a5f52e68a6b31a5898cda4f upstream.
The interrupt-status packet reports transmit credits returned by the device. edge_interrupt_callback() adds the 16-bit value to txCredits without checking maxTxCredits.
edge_write() uses txCredits minus the software FIFO count as the amount of data that fits. Since the FIFO is allocated with maxTxCredits bytes, txCredits exceeding maxTxCredits can cause OOB write in ring buffer.
Cap accumulated credits at maxTxCredits. Conforming devices should never hit the cap.
--- drivers/usb/serial/io_edgeport.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/usb/serial/io_edgeport.c +2 -1
@@ -646,7 +646,8 @@ static void edge_interrupt_callback(struif (edge_port && edge_port->open) {spin_lock_irqsave (&edge_port->ep_lock, flags); - edge_port->txCredits += txCredits; + edge_port->txCredits =min (edge_port->txCredits + txCredits, + edge_port->maxTxCredits);spin_unlock_irqrestore (&edge_port->ep_lock, flags); dev_dbg(dev, "%s - txcredits for port%d = %d\n",
Greg Kroah-Hartman
maintainerPATCH 155/744 USB: serial: keyspan_pda: fix data loss on receive throttling
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit 42a97c0480f96a2977e6d51ce512adc780f1ef5d upstream.
Killing the interrupt-in urb when the line disciple requests throttling may lead to data loss if an ongoing transfer is cancelled.
Instead set a flag to prevent the completion handler from resubmitting the urb until the port is unthrottled.
--- drivers/usb/serial/keyspan_pda.c | 44 +++++++++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 9 deletions(-)
drivers/usb/serial/keyspan_pda.c +35 -9
@@ -35,6 +35,8 @@ struct keyspan_pda_private {struct work_struct unthrottle_work;struct usb_serial *serial;struct usb_serial_port *port; +bool throttled; +bool throttle_req; };static int keyspan_pda_write_start (struct usb_serial_port *port);
@@ -150,6 +152,7 @@ static void keyspan_pda_rx_interrupt(strint retval;int status = urb->status;struct keyspan_pda_private *priv; +bool throttled = false;unsigned long flags; priv =usb_get_serial_port_data (port);
@@ -211,16 +214,24 @@ static void keyspan_pda_rx_interrupt(str } exit: - retval =usb_submit_urb (urb,GFP_ATOMIC ); -if (retval) -dev_err (&port->dev, -"%s - usb_submit_urb failed with result %d\n" , - __func__, retval); +spin_lock_irqsave (&port->lock, flags); +if (priv->throttle_req) { + priv->throttled = true; + throttled = true; + } +spin_unlock_irqrestore (&port->lock, flags); + +if (!throttled) { + retval =usb_submit_urb (urb,GFP_ATOMIC ); +if (retval) +dev_err (&port->dev,"failed to resubmit in urb: %d\n" , retval); + } }static void keyspan_pda_rx_throttle (struct tty_struct *tty) {struct usb_serial_port *port = tty->driver_data; +struct keyspan_pda_private *priv =usb_get_serial_port_data (port);/* * Stop receiving characters. We just turn off the URB request, and
@@ -230,16 +241,29 @@ static void keyspan_pda_rx_throttle(stru* send an XOFF, although it might make sense to foist that off upon * the device too. */ -usb_kill_urb (port->interrupt_in_urb); +spin_lock_irq (&port->lock); + priv->throttle_req = true; +spin_unlock_irq (&port->lock); }static void keyspan_pda_rx_unthrottle (struct tty_struct *tty) {struct usb_serial_port *port = tty->driver_data; +struct keyspan_pda_private *priv =usb_get_serial_port_data (port); +bool throttled; +int ret; + +spin_lock_irq (&port->lock); + throttled = priv->throttled; + priv->throttled = false; + priv->throttle_req = false; +spin_unlock_irq (&port->lock); -/* just restart the receive interrupt URB */ -if (usb_submit_urb (port->interrupt_in_urb,GFP_KERNEL )) -dev_dbg (&port->dev,"usb_submit_urb(read urb) failed\n" ); +if (throttled) { + ret =usb_submit_urb (port->interrupt_in_urb,GFP_KERNEL ); +if (ret) +dev_err (&port->dev,"failed to submit in urb: %d\n" , ret); + } }static speed_t keyspan_pda_setbaud (struct usb_serial *serial,speed_t baud)
@@ -579,6 +603,8 @@ static int keyspan_pda_open(struct tty_sspin_lock_irq (&port->lock); priv->tx_room = rc; + priv->throttled = false; + priv->throttle_req = false;spin_unlock_irq (&port->lock); rc =usb_submit_urb (port->interrupt_in_urb,GFP_KERNEL );
Greg Kroah-Hartman
maintainerPATCH 156/744 USB: serial: option: add TDTECH MT5710-CN
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chukun Pan <[email protected]>
commit 55645e4f3c6022ffb160ad3617d2b624eaa38501 upstream.
Add support for the TDTECH MT5710-CN (5G redcap) module based on the Huawei HiSilicon Balong chip.
T: Bus=01 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#= 3 Spd=480 MxCh= 0 D: Ver= 2.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 P: Vendor=3466 ProdID=3301 Rev=ff.ff S: Manufacturer=TD Tech Ltd. S: Product=TDTECH MT571X S: SerialNumber=0123456789ABCDEF C:* #Ifs= 6 Cfg#= 1 Atr=c0 MxPwr= 0mA A: FirstIf#= 0 IfCount= 2 Cls=02(comm.) Sub=0d Prot=00 I:* If#= 0 Alt= 0 #EPs= 1 Cls=02(comm.) Sub=0d Prot=00 Driver=cdc_ncm E: Ad=82(I) Atr=03(Int.) MxPS= 16 Ivl=32ms I: If#= 1 Alt= 0 #EPs= 0 Cls=0a(data ) Sub=00 Prot=01 Driver=cdc_ncm I:* If#= 1 Alt= 1 #EPs= 2 Cls=0a(data ) Sub=00 Prot=01 Driver=cdc_ncm E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms I:* If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=06 Prot=13 Driver=option E: Ad=83(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms I:* If#= 3 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=06 Prot=12 Driver=option E: Ad=84(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms I:* If#= 4 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=06 Prot=1c Driver=option E: Ad=85(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms I:* If#= 5 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=06 Prot=14 Driver=option E: Ad=86(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=05(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
Interface: ECM / NCM + DIAG + AT + SERIAL + GPS
--- drivers/usb/serial/option.c | 1 + 1 file changed, 1 insertion(+)
drivers/usb/serial/option.c +1 -0
@@ -2497,6 +2497,7 @@ static const struct usb_device_id option .driver_info = RSVD(5) }, { USB_DEVICE_INTERFACE_CLASS(0x33f8, 0x1003, 0xff), /* Rolling RW135R-GL (laptop MBIM) */ .driver_info = RSVD(5) }, + { USB_DEVICE_INTERFACE_CLASS(0x3466, 0x3301, 0xff) }, /* TDTECH MT5710-CN */ { USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0100, 0xff, 0xff, 0x30) }, /* NetPrisma LCUK54-WWD for Global */ { USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0100, 0xff, 0x00, 0x40) }, { USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0100, 0xff, 0xff, 0x40) },
Greg Kroah-Hartman
maintainerPATCH 157/744 usb: typec: ucsi: Detect and skip duplicate altmodes from buggy firmware
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chia-Lin Kao (AceLan) <[email protected]>
commit 67c92c6419ea6dbc5b1f3e9691aecea956e3e81c upstream.
Some firmware implementations incorrectly return the same altmode multiple times at different offsets when queried via UCSI_GET_ALTERNATE_MODES. This causes sysfs duplicate filename errors and kernel call traces when the driver attempts to register the same altmode twice:
sysfs: cannot create duplicate filename '/devices/.../typec/port0/port0.0/partner' typec-thunderbolt port0-partner.1: failed to create symlinks typec-thunderbolt port0-partner.1: probe with driver typec-thunderbolt failed with error -17
The matching rules differ by recipient:
- UCSI_RECIPIENT_CON (port) and UCSI_RECIPIENT_SOP_P (plug):
Two altmodes with identical SVID and VDO are byte-for-byte duplicates and the second has no observable function, so drop it.
- UCSI_RECIPIENT_SOP (partner):
The typec class binds each partner altmode to a port altmode of the same SVID via altmode_match()/device_find_child(), which returns the first port altmode with a matching SVID. If the partner advertises more altmodes for SVID X than the port advertises, the surplus partner altmode(s) collapse onto an already-paired port altmode and trigger the
"duplicate filename .../partner" sysfs error during typec_altmode_create_links(). Use the port-side altmode count for SVID X as the authoritative cap and reject any partner altmode that would exceed it. This preserves legitimate multi-Mode partner altmodes (vendor SVIDs that the port really does advertise more than once) while filtering the firmware-generated duplicates that have no port counterpart, and is therefore stricter than a plain SVID+VDO comparison (which still admits the Thunderbolt case where firmware reports the same SVID twice with different VDOs) without being over-broad like a plain SVID match (which would falsely drop legitimate vendor multi-Mode entries).
If a duplicate is detected, skip it and emit a clean warning instead of generating a kernel call trace:
ucsi_acpi USBC000:00: con2: Firmware bug: duplicate partner altmode SVID 0x8087 at offset 1, ignoring. ucsi_acpi USBC000:00: con2: VDO mismatch: 0x8087a043 vs 0x00000001
The duplicate detection logic lives in a reusable helper ucsi_altmode_is_duplicate() and is invoked from ucsi_register_altmodes(). It applies to all three recipient types:
partner (SOP), port (CON), and plug (SOP_P) altmodes.
unchanged: still SVID+VDO exact-dup match.
--- drivers/usb/typec/ucsi/ucsi.c | 132 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+)
drivers/usb/typec/ucsi/ucsi.c +132 -0
@@ -498,6 +498,129 @@ err:return ret; } +static void ucsi_dump_duplicate_altmode (struct ucsi_connector *con, +u8 recipient,u16 svid, +u32 existing_vdo,u32 new_vdo, +int offset) +{ +static const char *const recipient_names[] = { + [UCSI_RECIPIENT_CON ] ="port" , + [UCSI_RECIPIENT_SOP ] ="partner" , + [UCSI_RECIPIENT_SOP_P ] ="plug" , + [UCSI_RECIPIENT_SOP_PP ] ="cable plug prime" , + }; + +dev_warn (con->ucsi->dev, +"con%d: Firmware bug: duplicate %s altmode SVID 0x%04x at offset %d, ignoring but please contact the BIOS vendor to fix this issue.\n" , + con->num, recipient_names[recipient], svid, offset); + +if (existing_vdo != new_vdo) +dev_warn (con->ucsi->dev, +"con%d: VDO mismatch: 0x%08x vs 0x%08x\n" , + con->num, existing_vdo, new_vdo); +} + +/* Count altmodes in @altmodes that advertise @svid. */ +static int ucsi_altmode_count_svid (struct typec_altmode **altmodes,u16 svid) +{ +int count =0 ; +int k; + +for (k =0 ; k <UCSI_MAX_ALTMODES ; k++) { +if (!altmodes[k]) +break ; +if (altmodes[k]->svid == svid) + count++; + } + +return count; +} + +/* +* Check if an altmode is a duplicate. Some firmware implementations +* incorrectly return the same altmode multiple times, causing sysfs errors. +* Returns true if the altmode should be skipped. +* +* The matching rules differ by recipient: +* +* - UCSI_RECIPIENT_CON (port) and UCSI_RECIPIENT_SOP_P (plug): +* Two altmodes with identical SVID and VDO are byte-for-byte duplicates +* and the second has no observable function. Drop them. +* +* - UCSI_RECIPIENT_SOP (partner): +* The typec class binds each partner altmode to a port altmode of the +* same SVID via altmode_match()/device_find_child(), which returns the +* first port altmode with a matching SVID. If the partner advertises +* more altmodes for SVID X than the port advertises, the surplus +* partner altmode(s) collapse onto an already-paired port altmode and +* trigger a "duplicate filename .../partner" sysfs error during +* typec_altmode_create_links(). Use the port-side altmode count for +* SVID X as the authoritative cap and reject any partner altmode that +* would exceed it. This preserves legitimate multi-Mode partner +* altmodes (e.g. vendor SVIDs that the port really does advertise +* twice) while filtering the firmware-generated duplicates that have +* no port counterpart. +*/ +static bool ucsi_altmode_is_duplicate (struct ucsi_connector *con,u8 recipient, +const struct ucsi_altmode *alt_batch,int batch_idx, +u16 svid,u32 vdo,int offset) +{ +struct typec_altmode **altmodes; +int port_count, partner_count; +int k; + +/* Check for duplicates within the current batch first */ +for (k =0 ; k < batch_idx; k++) { +if (alt_batch[k].svid == svid && alt_batch[k].mid == vdo) { +ucsi_dump_duplicate_altmode (con, recipient, svid, + vdo, vdo, offset); +return true; + } + } + +switch (recipient) { +case UCSI_RECIPIENT_SOP : +/* +* Cap partner altmodes per SVID by the port-side count: +* any further partner altmode for that SVID would alias an +* already-paired port altmode and break typec sysfs. +*/ + port_count =ucsi_altmode_count_svid (con->port_altmode, svid); + partner_count =ucsi_altmode_count_svid (con->partner_altmode, + svid); +if (port_count && partner_count >= port_count) { +ucsi_dump_duplicate_altmode (con, recipient, svid, + con->partner_altmode[partner_count -1 ]->vdo, + vdo, offset); +return true; + } +return false; +case UCSI_RECIPIENT_CON : + altmodes = con->port_altmode; +break ; +case UCSI_RECIPIENT_SOP_P : + altmodes = con->plug_altmode; +break ; +default : +return false; + } + +/* CON and SOP_P: drop only exact SVID+VDO duplicates. */ +for (k =0 ; k <UCSI_MAX_ALTMODES ; k++) { +if (!altmodes[k]) +break ; + +if (altmodes[k]->svid != svid || altmodes[k]->vdo != vdo) +continue ; + +ucsi_dump_duplicate_altmode (con, recipient, svid, + altmodes[k]->vdo, vdo, offset); +return true; + } + +return false; +} +static int ucsi_register_altmodes_nvidia (struct ucsi_connector *con,u8 recipient) {
@@ -622,6 +745,15 @@ static int ucsi_register_altmodes(structif (!alt[j].svid)return 0 ; +/* +* Check for duplicates in current batch and already +* registered altmodes. Skip if duplicate found. +*/ +if (ucsi_altmode_is_duplicate (con, recipient, alt, j, + alt[j].svid, alt[j].mid, + i - num + j)) +continue ; +memset (&desc,0 ,sizeof (desc)); desc.vdo = alt[j].mid; desc.svid = alt[j].svid;
Greg Kroah-Hartman
maintainerPATCH 158/744 usb: typec: ucsi: Add duplicate detection to nvidia registration path
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chia-Lin Kao (AceLan) <[email protected]>
commit f1aa17f72f9b9589bd724dc826c5b17d164193d1 upstream.
Extend the duplicate altmode detection to ucsi_register_altmodes_nvidia() which is used when a driver provides the update_altmodes() callback.
This ensures all drivers benefit from duplicate detection, whether they use the standard registration path or the nvidia path with update_altmodes callback.
Without this fix, drivers using the nvidia path (like yoga_c630) would still encounter duplicate altmode registration errors from buggy firmware.
--- drivers/usb/typec/ucsi/ucsi.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-)
drivers/usb/typec/ucsi/ucsi.c +16 -10
@@ -675,19 +675,25 @@ ucsi_register_altmodes_nvidia(struct ucs/* now register altmodes */ for (i =0 ; i < max_altmodes; i++) { -memset (&desc,0 ,sizeof (desc)); -if (multi_dp) { - desc.svid = updated[i].svid; - desc.vdo = updated[i].mid; - }else { - desc.svid = orig[i].svid; - desc.vdo = orig[i].mid; - } - desc.roles =TYPEC_PORT_DRD ; +struct ucsi_altmode *altmode_array = multi_dp ? updated : orig; -if (!desc.svid) +if (!altmode_array[i].svid)return 0 ; +/* +* Check for duplicates in current array and already +* registered altmodes. Skip if duplicate found. +*/ +if (ucsi_altmode_is_duplicate (con, recipient, altmode_array, i, + altmode_array[i].svid, + altmode_array[i].mid, i)) +continue ; + +memset (&desc,0 ,sizeof (desc)); + desc.svid = altmode_array[i].svid; + desc.vdo = altmode_array[i].mid; + desc.roles =TYPEC_PORT_DRD ; + ret =ucsi_register_altmode (con, &desc, recipient);if (ret)return ret;
Greg Kroah-Hartman
maintainerPATCH 159/744 drm/amd/display: Fix ISM dc_lock deadlock during suspend
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ray Wu <[email protected]>
[ Upstream commit 3714fe242592e3699ac5e2c19d68b275a210be7d ]
[Why]
System hang observed during suspend/resume while video is playing. amdgpu_dm_ism_disable() is called under dc_lock and waits for ISM delayed work via disable_delayed_work_sync(). The work handlers themselves take dc_lock, producing an ABBA deadlock when a worker is in flight at suspend time.
[How]
Split the disable path into two phases with opposite locking contracts:
1. amdgpu_dm_ism_disable() -- quiesces workers, must NOT hold dc_lock.
2. amdgpu_dm_ism_force_full_power() (new) -- drives the ISM FSM back to FULL_POWER_RUNNING, must hold dc_lock.
--- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 25 +++++++-- .../drm/amd/display/amdgpu_dm/amdgpu_dm_ism.c | 56 ++++++++++++++++--- .../drm/amd/display/amdgpu_dm/amdgpu_dm_ism.h | 1 + 3 files changed, 70 insertions(+), 12 deletions(-)
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +21 -4
@@ -2260,9 +2260,16 @@ static void amdgpu_dm_fini(struct amdgpu_device *adev) adev->dm.idle_workqueue =NULL ; } -/* Disable ISM before dc_destroy() invalidates dm->dc */ +/* +* Disable ISM before dc_destroy() invalidates dm->dc. +* +* Quiesce workers first without dc_lock (they take dc_lock +* themselves, so syncing under it would deadlock), then drive the +* FSM back to FULL_POWER_RUNNING under dc_lock. +*/ +amdgpu_dm_ism_disable (&adev->dm); scoped_guard(mutex, &adev->dm.dc_lock) -amdgpu_dm_ism_disable (&adev->dm); +amdgpu_dm_ism_force_full_power (&adev->dm);amdgpu_dm_destroy_drm_device (&adev->dm);
@@ -3290,9 +3297,14 @@ static int dm_suspend(struct amdgpu_ip_block *ip_block)if (amdgpu_in_reset (adev)) {enum dc_status res; +/* Quiesce ISM workers before taking dc_lock (workers take +* dc_lock themselves; syncing under it would deadlock). +*/ +amdgpu_dm_ism_disable (dm); +mutex_lock (&dm->dc_lock); -amdgpu_dm_ism_disable (dm); +amdgpu_dm_ism_force_full_power (dm);dc_allow_idle_optimizations (adev->dm.dc, false); dm->cached_dc_state =dc_state_create_copy (dm->dc->current_state);
@@ -3326,8 +3338,13 @@ static int dm_suspend(struct amdgpu_ip_block *ip_block)amdgpu_dm_irq_suspend (adev); +/* +* Quiesce ISM workers before taking dc_lock (workers take dc_lock +* themselves; syncing under it would deadlock). +*/ +amdgpu_dm_ism_disable (dm); scoped_guard(mutex, &dm->dc_lock) -amdgpu_dm_ism_disable (dm); +amdgpu_dm_ism_force_full_power (dm);hpd_rx_irq_work_suspend (dm);
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_ism.c +48 -8
82 lines not on this page · raw message
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_ism.h +1 -0
@@ -146,6 +146,7 @@ void amdgpu_dm_ism_fini(struct amdgpu_dm_ism *ism);void amdgpu_dm_ism_commit_event (struct amdgpu_dm_ism *ism,enum amdgpu_dm_ism_event event);void amdgpu_dm_ism_disable (struct amdgpu_display_manager *dm); +void amdgpu_dm_ism_force_full_power (struct amdgpu_display_manager *dm);void amdgpu_dm_ism_enable (struct amdgpu_display_manager *dm);#endif
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 160/744 drm/amd/display: Fix preferred link rate for NUTMEG
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Timur Kristóf <[email protected]>
[ Upstream commit 9fb646bc4d87f62bcbf0a7ea326430eb802c475c ]
When there is a preferred link rate setting, it needs to be applied to both the current and initial link rate. This was regressed by a "coding style" fix, which caused the current link rate to not respect the preferred value.
This commit restores the functionality of NUTMEG, the DP bridge encoder found on old APUs such as Kaveri.
--- .../drm/amd/display/dc/link/protocols/link_dp_capability.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c +3 -1
@@ -750,8 +750,10 @@ static bool decide_dp_link_settings(struct dc_link *link, struct dc_link_settingif (req_bw >dp_link_bandwidth_kbps (link, &link->verified_link_cap))return false; -if (link->preferred_link_setting.link_rate !=LINK_RATE_UNKNOWN ) +if (link->preferred_link_setting.link_rate !=LINK_RATE_UNKNOWN ) { initial_link_setting.link_rate = link->preferred_link_setting.link_rate; + current_link_setting.link_rate = link->preferred_link_setting.link_rate; + }/* search for the minimum link setting that: * 1. is supported according to the link training result
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 161/744 drm/amd/display: Add dp_skip_rbr flag for NUTMEG
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Timur Kristóf <[email protected]>
[ Upstream commit e39b7cf5c62e027af166772e46382356ecb45c36 ]
No functional changes. Just clean up a conceptual mismatch.
Based on feedback on the NUTMEG code in DC, the preferred_link_setting is meant to force the DP link to a specific setting, meaning both the link rate and lane count should be locked to an exact value. What NUTMEG needs is a lower bound on the link rate, which is not the same concept.
Implement this as a HW workaround flag instead.
--- drivers/gpu/drm/amd/display/dc/dc.h | 2 ++ drivers/gpu/drm/amd/display/dc/link/link_detection.c | 2 +- .../drm/amd/display/dc/link/protocols/link_dp_capability.c | 6 +++--- 3 files changed, 6 insertions(+), 4 deletions(-)
drivers/gpu/drm/amd/display/dc/dc.h +2 -0
@@ -1727,6 +1727,8 @@ struct dc_scratch_space {bool dp_skip_DID2;bool dp_skip_reset_segment;bool dp_skip_fs_144hz; +/* Some DP bridges don't work with RBR and must use HBR. */ +bool dp_skip_rbr;bool dp_mot_reset_segment;/* Some USB4 docks do not handle turning off MST DSC once it has been enabled. */ bool dpia_mst_dsc_always_on;
drivers/gpu/drm/amd/display/dc/link/link_detection.c +1 -1
@@ -621,7 +621,7 @@ static bool detect_dp(struct dc_link *link, link->dpcd_caps.sink_count.bits.SINK_COUNT =1 ;/* NUTMEG requires that we use HBR, doesn't work with RBR. */ if (link->dpcd_caps.branch_dev_id ==DP_BRANCH_DEVICE_ID_00001A ) - link->preferred_link_setting.link_rate =LINK_RATE_HIGH ; + link->wa_flags.dp_skip_rbr = true; }return true;
drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c +3 -3
@@ -750,9 +750,9 @@ static bool decide_dp_link_settings(struct dc_link *link, struct dc_link_settingif (req_bw >dp_link_bandwidth_kbps (link, &link->verified_link_cap))return false; -if (link->preferred_link_setting.link_rate !=LINK_RATE_UNKNOWN ) { - initial_link_setting.link_rate = link->preferred_link_setting.link_rate; - current_link_setting.link_rate = link->preferred_link_setting.link_rate; +if (link->wa_flags.dp_skip_rbr) { + initial_link_setting.link_rate =LINK_RATE_HIGH ; + current_link_setting.link_rate =LINK_RATE_HIGH ; }/* search for the minimum link setting that:
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 162/744 wifi: mwifiex: fix freeze for 60 seconds caused by request_firmware
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Georgi Valkov <[email protected]>
[ Upstream commit 121a96c5a0db8d18e2ba2cb89660cca8a40508fe ]
Fix regression in rgpower table loading, caused by using request_firmware(): when the requested firmware does not exist, e.g. nxp/rgpower_WW.bin does not exist on OpenWRT builds for WRT3200ACM, request_firmware() falls back to firmware_fallback_sysfs(), which expects the firmware to be provided by user space using SYSFS. No such utility is provided in this configuration, so the entire system locks up for 60 seconds, until the request times out. During this time, no other log messages are observed, and the device does not respond to commands over UART.
The request_firmware() call is performed in the following context:current->comm kworker/1:2 in_task 1 irqs_disabled 0 in_atomic 0
Fixed by using request_firmware_direct(). This prevents fallback to SYSFS, and avoids delay. The rgpower table is optional. The driver falls back to the device tree power table if the firmware is not present.
The error code is printed for debugging and returned to the caller, which only cares for success or failure, so there are no side effects.
--- drivers/net/wireless/marvell/mwifiex/sta_ioctl.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-)
drivers/net/wireless/marvell/mwifiex/sta_ioctl.c +8 -6
@@ -196,6 +196,7 @@ static int mwifiex_request_rgpower_table(struct mwifiex_private *priv)struct mwifiex_adapter *adapter = priv->adapter;char rgpower_table_name[30 ];char country_code[3 ]; +int ret;strscpy (country_code, domain_info->country_code,sizeof (country_code));
@@ -214,16 +215,17 @@ static int mwifiex_request_rgpower_table(struct mwifiex_private *priv) adapter->rgpower_data =NULL ; } -if ((request_firmware (&adapter->rgpower_data, rgpower_table_name, - adapter->dev))) { + ret =request_firmware_direct (&adapter->rgpower_data, rgpower_table_name, + adapter->dev); + +if (ret) {mwifiex_dbg ( adapter,INFO , -"info: %s: failed to request regulatory power table\n" , - __func__); -return -EIO ; +"info: %s: failed to request regulatory power table: %d\n" , + __func__, ret); } -return 0 ; +return ret; }static int mwifiex_dnld_rgpower_table (struct mwifiex_private *priv)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 163/744 RISC-V: KVM: Serialize virtual interrupt pending state updates
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xie Bo <[email protected]>
commit d024a0a7879e6f37c0152aacf6d8e37b214a1738 upstream.
KVM RISC-V tracks guest local interrupt state with two bitmaps:
- irqs_pending: interrupts that should be visible to the guest
- irqs_pending_mask: interrupts whose pending state changed
The current code updates those bitmaps with independent atomic bitops and assumes a multiple-producer, single-consumer protocol. That model does not actually hold.
kvm_riscv_vcpu_sync_interrupts() is not a pure consumer. When the guest changes guest-visible HVIP state, sync_interrupts() writes both irqs_pending and irqs_pending_mask to reflect the new guest state back into KVM state. As a result, irqs_pending and irqs_pending_mask form a single logical state transition, but they are not updated atomically as a pair.
This allows a race where a newly injected interrupt is lost. For example:
CPU0 CPU1
---- ----
kvm_riscv_vcpu_set_interrupt(VS_SOFT)
set_bit(VS_SOFT, irqs_pending)
kvm_riscv_vcpu_sync_interrupts()
sees guest-cleared HVIP.VSSIP sets irqs_pending_mask clear_bit(IRQ_VS_SOFT, irqs_pending)
set_bit(VS_SOFT, irqs_pending_mask)
kvm_vcpu_kick()
After that interleaving, a later flush can update HVIP without VSSIP even though a new virtual interrupt was injected. In practice, the guest can remain blocked in WFI with work pending.
The same pending/mask protocol is shared by VS soft interrupts, PMU overflow delivery, and AIA high interrupt synchronization, so the race is not limited to one interrupt source.
Fix this by serializing all updates to irqs_pending and irqs_pending_mask with a per-vCPU raw spinlock. This keeps the pending bit and the dirty mask as one state transition across:
- set/unset interrupt
- guest HVIP sync
- interrupt flush to guest CSR state
- vCPU reset
- AIA CSR writes that clear dirty state
Use non-atomic bitmap operations while holding the lock. Hold the lock across the AIA sync, flush, and pending checks as well, so both bitmap words share the same serialization domain.
This intentionally replaces the existing lockless protocol instead of trying to repair it with additional barriers. The problem is not memory ordering on a single field; it is that two separate bitmaps encode one shared state machine while both producers and sync paths can modify them. A per-vCPU raw spinlock keeps the fix small, local, and suitable for backporting.
[ Adapted for 7.1.y: place the new 'unsigned long flags;' declaration in
kvm_riscv_vcpu_general_set_csr() explicitly. A direct apply anchors it in kvm_riscv_vcpu_general_get_csr(), whose prologue is byte-identical, leaving 'flags' undeclared at its use site. ]
--- arch/riscv/include/asm/kvm_host.h | 10 ++--- arch/riscv/kvm/aia.c | 35 ++++++++++++---- arch/riscv/kvm/vcpu.c | 68 ++++++++++++++++++++++--------- arch/riscv/kvm/vcpu_onereg.c | 8 +++- 4 files changed, 87 insertions(+), 34 deletions(-)
arch/riscv/include/asm/kvm_host.h +5 -5
@@ -207,13 +207,13 @@ struct kvm_vcpu_arch {/* * VCPU interrupts * -* We have a lockless approach for tracking pending VCPU interrupts -* implemented using atomic bitops. The irqs_pending bitmap represent -* pending interrupts whereas irqs_pending_mask represent bits changed -* in irqs_pending. Our approach is modeled around multiple producer -* and single consumer problem where the consumer is the VCPU itself. +* The irqs_pending bitmap represents pending interrupts whereas +* irqs_pending_mask represents bits changed in irqs_pending. Updates +* to these bitmaps are serialized so vcpu interrupt sync/flush cannot +* drop a newly injected interrupt while syncing guest-visible HVIP. */ #define KVM_RISCV_VCPU_NR_IRQS 64 +raw_spinlock_t irqs_pending_lock;DECLARE_BITMAP (irqs_pending,KVM_RISCV_VCPU_NR_IRQS );DECLARE_BITMAP (irqs_pending_mask,KVM_RISCV_VCPU_NR_IRQS );
arch/riscv/kvm/aia.c +28 -7
@@ -51,12 +51,15 @@ void kvm_riscv_vcpu_aia_flush_interrupts(struct kvm_vcpu *vcpu)struct kvm_vcpu_aia_csr *csr = &vcpu->arch.aia_context.guest_csr;unsigned long mask, val; +lockdep_assert_held (&vcpu->arch.irqs_pending_lock); +if (!kvm_riscv_aia_available ())return ; -if (READ_ONCE (vcpu->arch.irqs_pending_mask[1 ])) { - mask =xchg_acquire (&vcpu->arch.irqs_pending_mask[1 ],0 ); - val =READ_ONCE (vcpu->arch.irqs_pending[1 ]) & mask; + mask = vcpu->arch.irqs_pending_mask[1 ]; +if (mask) { + vcpu->arch.irqs_pending_mask[1 ] =0 ; + val = vcpu->arch.irqs_pending[1 ] & mask; csr->hviph &= ~mask; csr->hviph |= val;
@@ -67,6 +70,8 @@ void kvm_riscv_vcpu_aia_sync_interrupts(struct kvm_vcpu *vcpu) {struct kvm_vcpu_aia_csr *csr = &vcpu->arch.aia_context.guest_csr; +lockdep_assert_held (&vcpu->arch.irqs_pending_lock); +if (kvm_riscv_aia_available ()) csr->vsieh =ncsr_read (CSR_VSIEH ); }
@@ -75,13 +80,22 @@ void kvm_riscv_vcpu_aia_sync_interrupts(struct kvm_vcpu *vcpu)bool kvm_riscv_vcpu_aia_has_interrupts (struct kvm_vcpu *vcpu,u64 mask) {unsigned long seip; +#ifdef CONFIG_32BIT +unsigned long flags; +bool pending; +#endif if (!kvm_riscv_aia_available ())return false;#ifdef CONFIG_32BIT -if (READ_ONCE (vcpu->arch.irqs_pending[1 ]) & - (vcpu->arch.aia_context.guest_csr.vsieh &upper_32_bits (mask))) +raw_spin_lock_irqsave (&vcpu->arch.irqs_pending_lock, flags); + pending = vcpu->arch.irqs_pending[1 ] & + (vcpu->arch.aia_context.guest_csr.vsieh & +upper_32_bits (mask)); +raw_spin_unlock_irqrestore (&vcpu->arch.irqs_pending_lock, flags); + +if (pending)return true;#endif
@@ -205,6 +219,9 @@ int kvm_riscv_vcpu_aia_set_csr(struct kvm_vcpu *vcpu, {struct kvm_vcpu_aia_csr *csr = &vcpu->arch.aia_context.guest_csr;unsigned long regs_max =sizeof (struct kvm_riscv_aia_csr ) /sizeof (unsigned long ); +#ifdef CONFIG_32BIT +unsigned long flags; +#endif if (!riscv_isa_extension_available (vcpu->arch.isa,SSAIA ))return -ENOENT ;
@@ -217,8 +234,12 @@ int kvm_riscv_vcpu_aia_set_csr(struct kvm_vcpu *vcpu, ((unsigned long *)csr)[reg_num] = val;#ifdef CONFIG_32BIT -if (reg_num ==KVM_REG_RISCV_CSR_AIA_REG (siph)) -WRITE_ONCE (vcpu->arch.irqs_pending_mask[1 ],0 ); +if (reg_num ==KVM_REG_RISCV_CSR_AIA_REG (siph)) { +raw_spin_lock_irqsave (&vcpu->arch.irqs_pending_lock, flags); + vcpu->arch.irqs_pending_mask[1 ] =0 ; +raw_spin_unlock_irqrestore (&vcpu->arch.irqs_pending_lock, + flags); + }#endif }
arch/riscv/kvm/vcpu.c +48 -20
164 lines not on this page · raw message
arch/riscv/kvm/vcpu_onereg.c +6 -2
@@ -298,6 +298,7 @@ static int kvm_riscv_vcpu_general_set_csr(struct kvm_vcpu *vcpu, {struct kvm_vcpu_csr *csr = &vcpu->arch.guest_csr;unsigned long regs_max =sizeof (struct kvm_riscv_csr ) /sizeof (unsigned long ); +unsigned long flags;if (reg_num >= regs_max)return -ENOENT ;
@@ -311,8 +312,11 @@ static int kvm_riscv_vcpu_general_set_csr(struct kvm_vcpu *vcpu, ((unsigned long *)csr)[reg_num] = reg_val; -if (reg_num ==KVM_REG_RISCV_CSR_REG (sip)) -WRITE_ONCE (vcpu->arch.irqs_pending_mask[0 ],0 ); +if (reg_num ==KVM_REG_RISCV_CSR_REG (sip)) { +raw_spin_lock_irqsave (&vcpu->arch.irqs_pending_lock, flags); + vcpu->arch.irqs_pending_mask[0 ] =0 ; +raw_spin_unlock_irqrestore (&vcpu->arch.irqs_pending_lock, flags); + }return 0 ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 164/744 Revert "drm/amd/display: Add missing kdoc for ALLM parameters"
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
This reverts commit 994a42b890cef46cd576a3bf700f1dbd6bb21346.
--- drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c | 2 -- 1 file changed, 2 deletions(-)
drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c +0 -2
@@ -502,8 +502,6 @@ void mod_build_vsc_infopacket(const struct dc_stream_state *stream,* * @stream: contains data we may need to construct VSIF (i.e. timing_3d_format, etc.) * @info_packet: output structure where to store VSIF -* @ALLMEnabled: indicates whether ALLM HF-VSIF should be generated -* @ALLMValue: ALLM bit value to advertise in HF-VSIF */ void mod_build_hf_vsif_infopacket (const struct dc_stream_state *stream,struct dc_info_packet *info_packet)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 165/744 usb: xhci-pci: Limit VIA VL805 DMA addressing to 36 bits
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xincheng Zhang <[email protected]>
commit 1fc50f1ecde39feb4fccdaf4bc71aa6c0eb25c49 upstream.
The VIA VL805/806 xHCI controller advertises AC64, but fails to handle DMA addresses at or above 0x1000000000. On systems with large amounts of RAM, this can cause USB device failures when the controller is given DMA addresses beyond its usable address width.
Do not use XHCI_NO_64BIT_SUPPORT for this controller. That quirk clears the cached AC64 capability and limits DMA to 32 bits, causing unnecessary bouncing for addresses between 4GiB and 64GiB and hiding the controller's real AC64 capability from code that may need to distinguish register access width from usable DMA address width.
Track the usable DMA address width separately from the AC64 capability. Initialize the generic xhci->dma_mask_bits field to 64 and let PCI quirks reduce it for controllers with narrower DMA support. Set VIA VL805/806 to 36 bits so the DMA API only hands it addresses in the range it can handle while keeping HCCPARAMS1.AC64 visible.
--- drivers/usb/host/xhci-pci.c | 1 + drivers/usb/host/xhci.c | 15 ++++++++++----- drivers/usb/host/xhci.h | 1 + 3 files changed, 12 insertions(+), 5 deletions(-)
drivers/usb/host/xhci-pci.c +1 -0
@@ -448,6 +448,7 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)if (pdev->vendor ==PCI_VENDOR_ID_VIA && pdev->device ==PCI_DEVICE_ID_VIA_VL805 ) { xhci->quirks |=XHCI_LPM_SUPPORT ; xhci->quirks |=XHCI_TRB_OVERFETCH ; + xhci->dma_mask_bits =36 ; } if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA &&
drivers/usb/host/xhci.c +10 -5
@@ -5469,6 +5469,7 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)if (xhci->hci_version >0x100 ) xhci->hcc_params2 =readl (&xhci->cap_regs->hcc_params2); + xhci->dma_mask_bits =64 ; xhci->max_slots =HCS_MAX_SLOTS (hcs_params1); xhci->max_ports =min (HCS_MAX_PORTS (hcs_params1),MAX_HC_PORTS );/* xhci-plat or xhci-pci might have set max_interrupters already */
@@ -5518,12 +5519,16 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)if (xhci->quirks &XHCI_NO_64BIT_SUPPORT ) xhci->hcc_params &= ~BIT (0 ); -/* Set dma_mask and coherent_dma_mask to 64-bits, -* if xHC supports 64-bit addressing */ +/* +* Set dma_mask and coherent_dma_mask to 64-bits if xHC supports +* 64-bit addressing, unless a controller-specific quirk callback +* limits the usable address width. +*/ if ((xhci->hcc_params &HCC_64BIT_ADDR ) && - !dma_set_mask (dev,DMA_BIT_MASK (64 ))) { -xhci_dbg (xhci,"Enabling 64-bit DMA addresses.\n" ); -dma_set_coherent_mask (dev,DMA_BIT_MASK (64 )); + !dma_set_mask (dev,DMA_BIT_MASK (xhci->dma_mask_bits))) { +xhci_dbg (xhci,"Enabling %u-bit DMA addresses.\n" , + xhci->dma_mask_bits); +dma_set_coherent_mask (dev,DMA_BIT_MASK (xhci->dma_mask_bits)); }else {/* * This is to avoid error in cases where a 32-bit USB
drivers/usb/host/xhci.h +1 -0
@@ -1524,6 +1524,7 @@ struct xhci_hcd {/* imod_interval in ns (I * 250ns) */ u32 imod_interval;u32 page_size; +unsigned int dma_mask_bits;/* MSI-X/MSI vectors */ int nvecs;/* optional clocks */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 166/744 selftests/bpf: Adjust verifier_map_ptr for the maps excl field
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: KP Singh <[email protected]>
commit 38498c0ebacd54dbaac3513a548a13f1a8455c4e upstream.
Adding the u32 excl field at offset 32 of struct bpf_map right after the sha[SHA256_DIGEST_SIZE] hash shifts the ops pointer from offset 32 to 40. Therefore, fix up the test case.
# LDLIBS=-static PKG_CONFIG='pkg-config --static' ./vmtest.sh -- ./test_progs -t verifier_map_ptr [...]
#637/1 verifier_map_ptr/bpf_map_ptr: read with negative offset rejected:OK #637/2 verifier_map_ptr/bpf_map_ptr: read with negative offset rejected @unpriv:OK #637/3 verifier_map_ptr/bpf_map_ptr: write rejected:OK #637/4 verifier_map_ptr/bpf_map_ptr: write rejected @unpriv:OK #637/5 verifier_map_ptr/bpf_map_ptr: read non-existent field rejected:OK #637/6 verifier_map_ptr/bpf_map_ptr: read non-existent field rejected @unpriv:OK #637/7 verifier_map_ptr/bpf_map_ptr: read ops field accepted:OK #637/8 verifier_map_ptr/bpf_map_ptr: read ops field accepted @unpriv:OK
[...]
Summary: 2/18 PASSED, 0 SKIPPED, 0 FAILED
--- tools/testing/selftests/bpf/progs/verifier_map_ptr.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
tools/testing/selftests/bpf/progs/verifier_map_ptr.c +5 -3
@@ -70,13 +70,15 @@ __naked void bpf_map_ptr_write_rejected(void) : __clobber_all); } -/* The first element of struct bpf_map is a SHA256 hash of 32 bytes, accessing -* into this array is valid. The opts field is now at offset 33. +/* +* struct bpf_map starts with the SHA256 hash sha[32] at offset 0 (a readable +* byte array), followed by the u32 excl field at offset 32. Reading a u32 at +* offset 33 runs past the end of excl and is rejected. */ SEC("socket") __description("bpf_map_ptr: read non-existent field rejected") __failure -__msg("cannot access ptr member ops with moff 32 in struct bpf_map with off 33 size 4") +__msg("access beyond the end of member excl (mend:36) in struct bpf_map with off 33 size 4") __failure_unpriv __msg_unpriv("access is allowed only to CAP_PERFMON and CAP_SYS_ADMIN")__flag (BPF_F_ANY_ALIGNMENT )
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 167/744 selftests/bpf: Keep verifier_map_ptr exercising ops pointer access
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Daniel Borkmann <[email protected]>
commit 082c412097716b93ff1365689fc4ddcd1ce8296f upstream.
sashiko complained that 38498c0ebacd ("selftests/bpf: Adjust verifier_map_ptr for the map's excl field") would slightly decrease the test coverage given before the test was against the verifier rejecting the ops pointer. Recover the old test with the right offsets and add the existing one as an additional test case.
# LDLIBS=-static PKG_CONFIG='pkg-config --static' ./vmtest.sh -- ./test_progs -t verifier_map_ptr
[ 1.672932] bpf_testmod: module verification failed: signature and/or required key missing - tainting kernel #637/1 verifier_map_ptr/bpf_map_ptr: read with negative offset rejected:OK #637/2 verifier_map_ptr/bpf_map_ptr: read with negative offset rejected @unpriv:OK #637/3 verifier_map_ptr/bpf_map_ptr: write rejected:OK #637/4 verifier_map_ptr/bpf_map_ptr: write rejected @unpriv:OK #637/5 verifier_map_ptr/bpf_map_ptr: read non-existent field rejected:OK #637/6 verifier_map_ptr/bpf_map_ptr: read non-existent field rejected @unpriv:OK #637/7 verifier_map_ptr/bpf_map_ptr: read beyond excl field rejected:OK #637/8 verifier_map_ptr/bpf_map_ptr: read beyond excl field rejected @unpriv:OK #637/9 verifier_map_ptr/bpf_map_ptr: read ops field accepted:OK #637/10 verifier_map_ptr/bpf_map_ptr: read ops field accepted @unpriv:OK #637/11 verifier_map_ptr/bpf_map_ptr: r = 0, map_ptr = map_ptr + r:OK #637/12 verifier_map_ptr/bpf_map_ptr: r = 0, map_ptr = map_ptr + r @unpriv:OK #637/13 verifier_map_ptr/bpf_map_ptr: r = 0, r = r + map_ptr:OK #637/14 verifier_map_ptr/bpf_map_ptr: r = 0, r = r + map_ptr @unpriv:OK #637 verifier_map_ptr:OK [...] Summary: 2/20 PASSED, 0 SKIPPED, 0 FAILED
--- .../selftests/bpf/progs/verifier_map_ptr.c | 34 ++++++++++++++++--- 1 file changed, 30 insertions(+), 4 deletions(-)
tools/testing/selftests/bpf/progs/verifier_map_ptr.c +30 -4
@@ -72,17 +72,43 @@ __naked void bpf_map_ptr_write_rejected(void)/* * struct bpf_map starts with the SHA256 hash sha[32] at offset 0 (a readable -* byte array), followed by the u32 excl field at offset 32. Reading a u32 at -* offset 33 runs past the end of excl and is rejected. +* byte array), the u32 excl field at offset 32, and the ops pointer at offset +* 40. Reading a u32 at offset 41 reaches into the middle of the ops pointer, +* i.e. a partial pointer access, which is rejected. */ SEC("socket") __description("bpf_map_ptr: read non-existent field rejected") __failure -__msg("access beyond the end of member excl (mend:36) in struct bpf_map with off 33 size 4") +__msg("cannot access ptr member ops with moff 40 in struct bpf_map with off 41 size 4") __failure_unpriv __msg_unpriv("access is allowed only to CAP_PERFMON and CAP_SYS_ADMIN")__flag (BPF_F_ANY_ALIGNMENT) __naked void read_non_existent_field_rejected(void) +{ + asmvolatile (" \ +r6 = 0; \ +r1 = %[map_array_48b] ll; \ +r6 = *(u32*)(r1 + 41); \ +r0 = 1; \ +exit; \ +" : + : __imm_addr(map_array_48b) + : __clobber_all); +} + +/* +* The u32 excl field spans offsets 32..35 (mend 36). Reading a u32 at offset +* 33 starts inside excl but extends past its end, which the verifier rejects +* as an out-of-bounds scalar access. +*/ +SEC("socket") +__description("bpf_map_ptr: read beyond excl field rejected") +__failure +__msg("access beyond the end of member excl (mend:36) in struct bpf_map with off 33 size 4") +__failure_unpriv +__msg_unpriv("access is allowed only to CAP_PERFMON and CAP_SYS_ADMIN") +__flag (BPF_F_ANY_ALIGNMENT) +__naked void read_beyond_excl_field_rejected(void) { asm volatile (" \ r6 = 0; \
@@ -105,7 +131,7 @@ __naked void ptr_read_ops_field_accepted(void) asmvolatile (" \ r6 = 0; \ r1 = %[map_array_48b] ll; \ -r6 = *(u64*)(r1 + 0); \ +r6 = *(u64*)(r1 + 40); \ r0 = 1; \ exit; \ " :
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 168/744 watchdog: ni903x_wdt: Check ACPI_COMPANION() against NULL
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rafael J. Wysocki <[email protected]>
[ Upstream commit 36e05e134ee44f9fbfcebcbcdadb5f765fccd9f0 ]
Every platform driver can be forced to match a device that doesn't match its list of device IDs because of device_match_driver_override(), so platform drivers that rely on the existence of a device's ACPI companion object need to verify its presence.
Accordingly, add a requisite ACPI_COMPANION() check against NULL to the ni903x_wdt watchdog driver.
--- drivers/watchdog/ni903x_wdt.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
drivers/watchdog/ni903x_wdt.c +6 -1
@@ -183,9 +183,14 @@ static int ni903x_acpi_probe(struct platform_device *pdev)struct device *dev = &pdev->dev;struct watchdog_device *wdd;struct ni903x_wdt *wdt; +acpi_handle handle;acpi_status status;int ret; + handle =ACPI_HANDLE (dev); +if (!handle) +return -ENODEV ; + wdt =devm_kzalloc (dev,sizeof (*wdt),GFP_KERNEL );if (!wdt)return -ENOMEM ;
@@ -193,7 +198,7 @@ static int ni903x_acpi_probe(struct platform_device *pdev)platform_set_drvdata (pdev, wdt); wdt->dev = dev; - status =acpi_walk_resources (ACPI_HANDLE (dev),METHOD_NAME__CRS , + status =acpi_walk_resources (handle,METHOD_NAME__CRS , ni903x_resources, wdt);if (ACPI_FAILURE (status) || wdt->io_base ==0 ) {dev_err (dev,"failed to get resources\n" );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 169/744 wifi: ath9k: hif_usb: dont dereference hif_dev after re-arming firmware request
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cheng Yongkang <[email protected]>
[ Upstream commit dad9f96945d77ecd4708f730c06ef54dcd8cc057 ]
ath9k_hif_request_firmware() re-arms an asynchronous firmware load via request_firmware_nowait(), passing hif_dev as the completion context, and then still dereferences hif_dev:
dev_info(&hif_dev->udev->dev, "ath9k_htc: Firmware %s requested\n", hif_dev->fw_name);
The re-armed callback ath9k_hif_usb_firmware_cb() runs on the "events" workqueue and, when the firmware is missing, walks the retry chain into ath9k_hif_usb_firmware_fail() -> complete_all(&hif_dev->fw_done). That releases the wait_for_completion(&hif_dev->fw_done) in a concurrent ath9k_hif_usb_disconnect(), which then kfree()s hif_dev. The trailing dev_info() in the frame that re-armed the request can therefore read freed memory (hif_dev->udev, the first field of struct hif_device_usb):
BUG: KASAN: slab-use-after-free in ath9k_hif_request_firmware Read of size 8 ... by task kworker/... ath9k_hif_request_firmware ath9k_hif_usb_firmware_cb drivers/net/wireless/ath/ath9k/hif_usb.c:1247 request_firmware_work_func Allocated by ...: ath9k_hif_usb_probe drivers/net/wireless/ath/ath9k/hif_usb.c Freed by ...: ath9k_hif_usb_disconnect -> kfree drivers/net/wireless/ath/ath9k/hif_usb.c
The fw_done barrier only makes disconnect wait for the firmware chain to *terminate*; it does not protect the outer ath9k_hif_request_firmware() frame that re-armed the request and keeps touching hif_dev afterwards.
Drop the post-request dev_info(): it is the only use of hif_dev after the async request is armed, and it is purely informational (the dev_err() on the failure path runs only when request_firmware_nowait() did not arm a callback, so hif_dev is still alive there).
This was first reported by syzbot as a single, non-reproduced crash that was later auto-obsoleted, and was independently rediscovered by the reFuzz fuzzer, which produced a C reproducer (USB-gadget connect/disconnect of an ath9k_htc device whose firmware download fails). The vulnerable code is unchanged and still present in v7.1-rc6, where the slab-use-after-free reproduces under KASAN once the (sub-microsecond) race window is widened.
--- drivers/net/wireless/ath/ath9k/hif_usb.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-)
drivers/net/wireless/ath/ath9k/hif_usb.c +1 -6
@@ -1225,15 +1225,10 @@ static int ath9k_hif_request_firmware(struct hif_device_usb *hif_dev, ret =request_firmware_nowait (THIS_MODULE , true, hif_dev->fw_name, &hif_dev->udev->dev,GFP_KERNEL , hif_dev, ath9k_hif_usb_firmware_cb); -if (ret) { +if (ret)dev_err (&hif_dev->udev->dev,"ath9k_htc: Async request for firmware %s failed\n" , hif_dev->fw_name); -return ret; - } - -dev_info (&hif_dev->udev->dev,"ath9k_htc: Firmware %s requested\n" , - hif_dev->fw_name);return ret; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 170/744 wifi: ath11k: fix NULL pointer dereference in ath11k_hal_srng_access_begin
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gaole Zhang <[email protected]>
[ Upstream commit e8d85672dd7e2523f774caafba8f858384e18df7 ]
In ATH11K_QMI_EVENT_FW_READY, ATH11K_FLAG_REGISTERED is set unconditionally even when ath11k_core_qmi_firmware_ready() fails. This leaves the driver in an inconsistent state where initialization is considered complete although the firmware ready handling did not finish successfully. During the subsequent SSR, the driver enters the restart path based on this incorrect state and dereferences uninitialized srng members, resulting in a NULL pointer dereference.
Call trace: ath11k_hal_srng_access_begin+0xc/0x60 [ath11k] (P) ath11k_ce_cleanup_pipes+0x17c/0x180 [ath11k] ath11k_core_restart+0x40/0x168 [ath11k]
Fix this by:
- skipping firmware_ready if ATH11K_FLAG_REGISTERED is already set
- setting ATH11K_FLAG_REGISTERED only when firmware_ready succeeds
- setting ATH11K_FLAG_QMI_FAIL and aborting the FW_READY handling on error
Tested-on: WCN6750 hw1.0 AHB WLAN.MSL.2.0.c2-00204-QCAMSLSWPLZ-1
--- drivers/net/wireless/ath/ath11k/qmi.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-)
drivers/net/wireless/ath/ath11k/qmi.c +8 -3
@@ -3295,9 +3295,14 @@ static void ath11k_qmi_driver_event_work(struct work_struct *work)clear_bit (ATH11K_FLAG_CRASH_FLUSH , &ab->dev_flags);clear_bit (ATH11K_FLAG_RECOVERY , &ab->dev_flags); -ath11k_core_qmi_firmware_ready (ab); -set_bit (ATH11K_FLAG_REGISTERED , &ab->dev_flags); - +if (!test_bit (ATH11K_FLAG_REGISTERED , &ab->dev_flags)) { + ret =ath11k_core_qmi_firmware_ready (ab); +if (ret) { +set_bit (ATH11K_FLAG_QMI_FAIL , &ab->dev_flags); +break ; + } +set_bit (ATH11K_FLAG_REGISTERED , &ab->dev_flags); + }break ;case ATH11K_QMI_EVENT_COLD_BOOT_CAL_DONE :break ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 171/744 hwmon: (corsair-psu) Stop device IO before calling hid_hw_stop
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Edward Adam Davis <[email protected]>
[ Upstream commit 9ab8656548cd737b98d0b19c4253aff8d68e97f4 ]
hid_hw_stop() does not stop the device IO.
This results in a race condition between hid_input_report() and the point immediately following the execution of hid_device_io_start() within corsairpsu_probe(). If the probe operation fails after "io start" has been initiated, this race condition will result in a uaf vulnerability [1].
CPU0 CPU1
==== ====corsairpsu_probe()
hid_device_io_start()
... unlock driver_input_lock
hid_hw_stop()
kfree(hidraw) __hid_input_report()
... acquire driver_input_lock hid_report_raw_event()
hidraw_report_event()
... access hidraw's list_lock // trigger uaf
Consequently, when corsairpsu_probe() fails and hid_hw_stop() needs to be executed, the io_started flag is first cleared while holding the driver_input_lock to prevent potential race conditions involving input reports.
[1]
BUG: KASAN: slab-use-after-free in rt_spin_lock+0x83/0x400 kernel/locking/spinlock_rt.c:56 Call Trace: hidraw_report_event+0x5d/0x3a0 drivers/hid/hidraw.c:577 hid_report_raw_event+0x311/0x1730 drivers/hid/hid-core.c:2076 __hid_input_report drivers/hid/hid-core.c:2152 [inline] hid_input_report+0x44e/0x580 drivers/hid/hid-core.c:2174 hid_irq_in+0x47e/0x6d0 drivers/hid/usbhid/hid-core.c:286 __usb_hcd_giveback_urb+0x3b3/0x5e0 drivers/usb/core/hcd.c:1657 dummy_timer+0x8a9/0x47d0 drivers/usb/gadget/udc/dummy_hcd.c:2005 Allocated by task 10: hidraw_connect+0x57/0x430 drivers/hid/hidraw.c:606 hid_connect+0x5bf/0x19d0 drivers/hid/hid-core.c:2277 hid_hw_start+0xa8/0x120 drivers/hid/hid-core.c:2387 corsairpsu_probe+0xd9/0x3c0 drivers/hwmon/corsair-psu.c:782 Freed by task 10: hidraw_disconnect+0x4f/0x60 drivers/hid/hidraw.c:662 hid_disconnect drivers/hid/hid-core.c:2362 [inline] hid_hw_stop+0x101/0x1e0 drivers/hid/hid-core.c:2407 corsairpsu_probe+0x327/0x3c0 drivers/hwmon/corsair-psu.c:826
Fix the problem by calling hid_device_io_stop() before calling hid_hw_stop().
[groeck: Updated subject and description;
call hid_device_io_stop() only if IO has been started]
--- drivers/hwmon/corsair-psu.c | 1 + 1 file changed, 1 insertion(+)
drivers/hwmon/corsair-psu.c +1 -0
@@ -822,6 +822,7 @@ static int corsairpsu_probe(struct hid_device *hdev, const struct hid_device_id fail_and_close:hid_hw_close (hdev); +hid_device_io_stop (hdev); fail_and_stop:hid_hw_stop (hdev);return ret;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 172/744 hwmon: (corsair-cpro) Stop device IO before calling hid_hw_stop
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guenter Roeck <[email protected]>
[ Upstream commit 94c87871b051d7ad758828a805215a2ec194512a ]
Calling hid_hw_stop() does not stop the device IO.
This results in a race condition between hid_input_report() and the point immediately following the execution of hid_device_io_start() within the driver probe function. If the probe operation fails after "io start" has been initiated, this race condition will result in a UAF vulnerability.
Fix the problem by calling hid_device_io_stop() before calling hid_hw_stop().
--- drivers/hwmon/corsair-cpro.c | 1 + 1 file changed, 1 insertion(+)
drivers/hwmon/corsair-cpro.c +1 -0
@@ -645,6 +645,7 @@ static int ccp_probe(struct hid_device *hdev, const struct hid_device_id *id) out_hw_close:hid_hw_close (hdev); +hid_device_io_stop (hdev); out_hw_stop:hid_hw_stop (hdev);return ret;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 173/744 hwmon: (gigabyte_waterforce) Stop device IO before calling hid_hw_stop
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guenter Roeck <[email protected]>
[ Upstream commit ff0c5c53d08274e200b48a4d53aa078265e873cb ]
Calling hid_hw_stop() does not stop the device IO.
This results in a race condition between hid_input_report() and the point immediately following the execution of hid_device_io_start() within the driver probe function. If the probe operation fails after "io start" has been initiated, this race condition will result in a UAF vulnerability.
Fix the problem by calling hid_device_io_stop() before calling hid_hw_stop().
--- drivers/hwmon/gigabyte_waterforce.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/hwmon/gigabyte_waterforce.c +3 -1
@@ -371,13 +371,15 @@ static int waterforce_probe(struct hid_device *hdev, const struct hid_device_idif (IS_ERR (priv->hwmon_dev)) { ret =PTR_ERR (priv->hwmon_dev);hid_err (hdev,"hwmon registration failed with %d\n" , ret); - goto fail_and_close; + goto fail_and_io_stop; }waterforce_debugfs_init (priv);return 0 ; +fail_and_io_stop: +hid_device_io_stop (hdev); fail_and_close:hid_hw_close (hdev); fail_and_stop:
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 174/744 hwmon: (nzxt-smart2) Stop device IO before calling hid_hw_stop
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guenter Roeck <[email protected]>
[ Upstream commit 59d104b54b0b42e30fd2a68d24ee5c49dcc54d1e ]
Calling hid_hw_stop() does not stop the device IO.
This results in a race condition between hid_input_report() and the point immediately following the execution of hid_device_io_start() within the driver probe function. If the probe operation fails after "io start" has been initiated, this race condition will result in a UAF vulnerability.
Fix the problem by calling hid_device_io_stop() before calling hid_hw_stop().
--- drivers/hwmon/nzxt-smart2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/hwmon/nzxt-smart2.c +1 -1
@@ -768,7 +768,7 @@ static int nzxt_smart2_hid_probe(struct hid_device *hdev, out_hw_close:hid_hw_close (hdev); - +hid_device_io_stop (hdev); out_hw_stop:hid_hw_stop (hdev);return ret;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 175/744 hwmon: (nzxt-kraken3) Stop device IO before calling hid_hw_stop
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guenter Roeck <[email protected]>
[ Upstream commit f151d0143ac4e086f92f52328ebdbdc50933d8ef ]
Calling hid_hw_stop() does not stop the device IO.
This results in a race condition between hid_input_report() and the point immediately following the execution of hid_device_io_start() within the driver probe function. If the probe operation fails after "io start" has been initiated, this race condition will result in a UAF vulnerability.
Fix the problem by calling hid_device_io_stop() before calling hid_hw_stop().
--- drivers/hwmon/nzxt-kraken3.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/hwmon/nzxt-kraken3.c +4 -2
@@ -948,7 +948,7 @@ static int kraken3_probe(struct hid_device *hdev, const struct hid_device_id *id ret =kraken3_init_device (hdev);if (ret <0 ) {hid_err (hdev,"device init failed with %d\n" , ret); - goto fail_and_close; + goto fail_and_stop_io; } ret =kraken3_get_fw_ver (hdev);
@@ -960,13 +960,15 @@ static int kraken3_probe(struct hid_device *hdev, const struct hid_device_id *idif (IS_ERR (priv->hwmon_dev)) { ret =PTR_ERR (priv->hwmon_dev);hid_err (hdev,"hwmon registration failed with %d\n" , ret); - goto fail_and_close; + goto fail_and_stop_io; }kraken3_debugfs_init (priv, device_name);return 0 ; +fail_and_stop_io: +hid_device_io_stop (hdev); fail_and_close:hid_hw_close (hdev); fail_and_stop:
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 176/744 watchdog: pretimeout: Fix UAF in watchdog_unregister_governor()
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tzung-Bi Shih <[email protected]>
[ Upstream commit 7362ba0f9c96ac3ad6a2ca3995bd9fc9a28a8661 ]
When a watchdog governor is unregistered, it updates existing watchdog devices that were using this governor by falling back to default_gov.
If the governor being unregistered is currently set as default_gov, the default_gov is never cleared. This leads to 2 use-after-free issues:
1. New watchdog devices registered after this point will inherit the dangling default_gov.
2. Existing watchdog devices using the unregistered governor will have their wdd->gov reassigned to the dangling default_gov.
Fix the UAF by clearing default_gov if it matches the governor being unregistered.
--- drivers/watchdog/watchdog_pretimeout.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/watchdog/watchdog_pretimeout.c +2 -0
@@ -167,6 +167,8 @@ void watchdog_unregister_governor(struct watchdog_governor *gov) }spin_lock_irq (&pretimeout_lock); +if (default_gov == gov) + default_gov =NULL ;list_for_each_entry (p, &pretimeout_list, entry)if (p->wdd->gov == gov) p->wdd->gov = default_gov;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 177/744 watchdog: airoha: Prevent division by zero when clock frequency is zero
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Wayen Yan <[email protected]>
[ Upstream commit bcfcd7619f277842430d197556463b401b839ee9 ]
clk_get_rate() can return 0 when the clock provider is not properly configured or the clock is unmanaged. The driver uses wdt_freq as a divisor directly in airoha_wdt_probe() to compute max_timeout and in airoha_wdt_get_timeleft() to compute the remaining time, which results in a division by zero.
Add a check for wdt_freq == 0 in probe and return -EINVAL with dev_err_probe() to prevent the division by zero and provide a diagnostic message.
--- drivers/watchdog/airoha_wdt.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/watchdog/airoha_wdt.c +3 -0
@@ -147,6 +147,9 @@ static int airoha_wdt_probe(struct platform_device *pdev)/* Watchdog ticks at half the bus rate */ airoha_wdt->wdt_freq =clk_get_rate (bus_clk) /2 ; +if (!airoha_wdt->wdt_freq) +return dev_err_probe (dev, -EINVAL , +"invalid clock frequency\n" );/* Initialize struct watchdog device */ wdog_dev = &airoha_wdt->wdog_dev;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 178/744 wifi: ath10k: fix skb leak on incomplete msdu during rx pop
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Manikanta Pubbisetty <[email protected]>
[ Upstream commit 7393878255e492515858f751ba4c260f248fb108 ]
When ath10k_htt_rx_pop_paddr32_list() or ath10k_htt_rx_pop_paddr64_list() encounters an incomplete frame (RX_ATTENTION_FLAGS_MSDU_DONE not set), it returns -EIO without purging the skb list built up so far, leaking any skbs already queued in the list.
Other early-exit paths within these same functions already call __skb_queue_purge() before returning an error. Add it before the -EIO return as well to be consistent and prevent the leak.
Tested-on: WCN3990 hw1.0 WLAN.HL.3.2.2.c10-00754-QCAHLSWMTPL-1
--- drivers/net/wireless/ath/ath10k/htt_rx.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/net/wireless/ath/ath10k/htt_rx.c +2 -0
@@ -707,6 +707,7 @@ static int ath10k_htt_rx_pop_paddr32_list(struct ath10k_htt *htt,if (!(__le32_to_cpu (rxd_attention->flags) &RX_ATTENTION_FLAGS_MSDU_DONE )) {ath10k_warn (htt->ar,"tried to pop an incomplete frame, oops!\n" ); +__skb_queue_purge (list);return -EIO ; } }
@@ -771,6 +772,7 @@ static int ath10k_htt_rx_pop_paddr64_list(struct ath10k_htt *htt,if (!(__le32_to_cpu (rxd_attention->flags) &RX_ATTENTION_FLAGS_MSDU_DONE )) {ath10k_warn (htt->ar,"tried to pop an incomplete frame, oops!\n" ); +__skb_queue_purge (list);return -EIO ; } }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 179/744 wifi: ath11k: fix potential buffer underflow in ath11k_hal_rx_msdu_list_get()
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Morgun <[email protected]>
[ Upstream commit 7f11e70629650ff6ea140984e5ce188b775b2683 ]
When the first entry in msdu_details has a zero buffer address, the code accesses msdu_details[i - 1] with i == 0, causing a buffer underflow.
Fix similarly to ath12k_wifi7_hal_rx_msdu_list_get() by adding a separate check for i == 0 before the main condition to prevent the out-of-bounds access.
Found by Linux Verification Center (linuxtesting.org) with SVACE.
--- drivers/net/wireless/ath/ath11k/dp_rx.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/net/wireless/ath/ath11k/dp_rx.c +3 -0
@@ -4565,6 +4565,9 @@ static void ath11k_hal_rx_msdu_list_get(struct ath11k *ar, msdu_details = &msdu_link->msdu_link[0 ];for (i =0 ; i <HAL_RX_NUM_MSDU_DESC ; i++) { +if (!i &&FIELD_GET (BUFFER_ADDR_INFO0_ADDR , + msdu_details[i].buf_addr_info.info0) ==0 ) +break ;if (FIELD_GET (BUFFER_ADDR_INFO0_ADDR , msdu_details[i].buf_addr_info.info0) ==0 ) { msdu_desc_info = &msdu_details[i -1 ].rx_msdu_info;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 180/744 wifi: ath11k: Flush the posted write after writing to PCIE_SOC_GLOBAL_RESET
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Manivannan Sadhasivam <[email protected]>
[ Upstream commit 0fe8010fc5b147607fc19ba010ba469afc95f35f ]
ath11k_pci_soc_global_reset() tries to reset the device by writing to the PCIE_SOC_GLOBAL_RESET register. But it doesn't do a read-back to ensure that the write gets flushed to the device before the delay.
This may lead to the delay on the host to be insufficient, if the posted write doesn't reach the device before the delay.
So add a read-back after writing to the PCIE_SOC_GLOBAL_RESET register and before the delay.
Compile tested only.
--- drivers/net/wireless/ath/ath11k/pci.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/net/wireless/ath/ath11k/pci.c +4 -0
@@ -199,6 +199,8 @@ static void ath11k_pci_soc_global_reset(struct ath11k_base *ab) val |=PCIE_SOC_GLOBAL_RESET_V ;ath11k_pcic_write32 (ab,PCIE_SOC_GLOBAL_RESET , val); +/* Flush the posted write to the device */ +ath11k_pcic_read32 (ab,PCIE_SOC_GLOBAL_RESET );/* TODO: exact time to sleep is uncertain */ delay =10 ;
@@ -208,6 +210,8 @@ static void ath11k_pci_soc_global_reset(struct ath11k_base *ab) val &= ~PCIE_SOC_GLOBAL_RESET_V ;ath11k_pcic_write32 (ab,PCIE_SOC_GLOBAL_RESET , val); +/* Flush the posted write to the device */ +ath11k_pcic_read32 (ab,PCIE_SOC_GLOBAL_RESET );mdelay (delay);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 181/744 wifi: ath12k: Flush the posted write after writing to PCIE_SOC_GLOBAL_RESET
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Manivannan Sadhasivam <[email protected]>
[ Upstream commit 55f3aa06951cac78b0206bde961c8cf11929a27a ]
ath12k_pci_soc_global_reset() tries to reset the device by writing to the PCIE_SOC_GLOBAL_RESET register. But it doesn't do a read-back to ensure that the write gets flushed to the device before the delay.
This may lead to the delay on the host to be insufficient, if the posted write doesn't reach the device before the delay.
So add a read-back after writing to the PCIE_SOC_GLOBAL_RESET register and before the delay.
Compile tested only.
Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.6-01243-QCAHKSWPL_SILICONZ-1
--- drivers/net/wireless/ath/ath12k/pci.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/net/wireless/ath/ath12k/pci.c +4 -0
@@ -188,6 +188,8 @@ static void ath12k_pci_soc_global_reset(struct ath12k_base *ab) val |=PCIE_SOC_GLOBAL_RESET_V ;ath12k_pci_write32 (ab,PCIE_SOC_GLOBAL_RESET , val); +/* Flush the posted write to the device */ +ath12k_pci_read32 (ab,PCIE_SOC_GLOBAL_RESET );/* TODO: exact time to sleep is uncertain */ delay =10 ;
@@ -197,6 +199,8 @@ static void ath12k_pci_soc_global_reset(struct ath12k_base *ab) val &= ~PCIE_SOC_GLOBAL_RESET_V ;ath12k_pci_write32 (ab,PCIE_SOC_GLOBAL_RESET , val); +/* Flush the posted write to the device */ +ath12k_pci_read32 (ab,PCIE_SOC_GLOBAL_RESET );mdelay (delay);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 182/744 platform/x86/intel/vsec: allocate res with intel_vsec_dev
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rosen Penev <[email protected]>
[ Upstream commit 8ef6b01cee44803691c0a0c95b36f8ec710e2afb ]
Use a flexible array member to combine allocations. Avoids having to free separately.
Add __counted_by for extra runtime analysis.
Move counting variable assignment to after allocations as is already done by kzalloc_flex for GCC 15 and above.
Stable-dep-of: 09b2ae290a24 ("platform/x86/intel/vsec: free ACPI discovery data on early errors")
--- drivers/platform/x86/intel/vsec.c | 14 ++++---------- drivers/platform/x86/intel/vsec_tpmi.c | 13 ++++--------- include/linux/intel_vsec.h | 6 +++--- 3 files changed, 11 insertions(+), 22 deletions(-)
drivers/platform/x86/intel/vsec.c +4 -10
@@ -112,7 +112,6 @@ static void intel_vsec_dev_release(struct device *dev)ida_free (intel_vsec_dev->ida, intel_vsec_dev->auxdev.id);kfree (intel_vsec_dev->acpi_disc); -kfree (intel_vsec_dev->resource);kfree (intel_vsec_dev); }
@@ -225,7 +224,6 @@ int intel_vsec_add_aux(struct device *parent, ret =xa_alloc (&auxdev_array, &intel_vsec_dev->id, intel_vsec_dev,PMT_XA_LIMIT ,GFP_KERNEL );if (ret <0 ) { -kfree (intel_vsec_dev->resource);kfree (intel_vsec_dev);return ret; }
@@ -233,7 +231,6 @@ int intel_vsec_add_aux(struct device *parent, id =ida_alloc (intel_vsec_dev->ida,GFP_KERNEL );if (id <0 ) {xa_erase (&auxdev_array, intel_vsec_dev->id); -kfree (intel_vsec_dev->resource);kfree (intel_vsec_dev);return id; }
@@ -282,7 +279,7 @@ static int intel_vsec_add_dev(struct device *dev, struct intel_vsec_header *head unsigned long cap_id, u64 base_addr) { struct intel_vsec_device __free(kfree) *intel_vsec_dev = NULL; - struct resource __free(kfree) *res = NULL; +struct resource *res;struct resource *tmp;struct device *parent;unsigned long quirks = info->quirks;
@@ -306,13 +303,12 @@ static int intel_vsec_add_dev(struct device *dev, struct intel_vsec_header *headreturn -EINVAL ; } - intel_vsec_dev =kzalloc_obj (*intel_vsec_dev); + intel_vsec_dev =kzalloc_flex (*intel_vsec_dev, resource, header->num_entries);if (!intel_vsec_dev)return -ENOMEM ; - res =kzalloc_objs (*res, header->num_entries); -if (!res) -return -ENOMEM ; + intel_vsec_dev->num_resources = header->num_entries; + res = intel_vsec_dev->resource;if (quirks &VSEC_QUIRK_TABLE_SHIFT ) header->offset >>=TABLE_OFFSET_SHIFT ;
@@ -342,8 +338,6 @@ static int intel_vsec_add_dev(struct device *dev, struct intel_vsec_header *head } intel_vsec_dev->dev = dev; - intel_vsec_dev->resource =no_free_ptr (res); - intel_vsec_dev->num_resources = header->num_entries; intel_vsec_dev->quirks = info->quirks; intel_vsec_dev->base_addr = info->base_addr; intel_vsec_dev->priv_data = info->priv_data;
drivers/platform/x86/intel/vsec_tpmi.c +4 -9
@@ -634,15 +634,12 @@ static int tpmi_create_device(struct intel_tpmi_info *tpmi_info,if (!name)return -EOPNOTSUPP ; - res =kzalloc_objs (*res, pfs->pfs_header.num_entries); -if (!res) + feature_vsec_dev =kzalloc_flex (*feature_vsec_dev, resource, pfs->pfs_header.num_entries); +if (!feature_vsec_dev)return -ENOMEM ; - feature_vsec_dev =kzalloc_obj (*feature_vsec_dev); -if (!feature_vsec_dev) { -kfree (res); -return -ENOMEM ; - } + feature_vsec_dev->num_resources = pfs->pfs_header.num_entries; + res = feature_vsec_dev->resource;snprintf (feature_id_name,sizeof (feature_id_name),"tpmi-%s" , name);
@@ -655,8 +652,6 @@ static int tpmi_create_device(struct intel_tpmi_info *tpmi_info, } feature_vsec_dev->dev = vsec_dev->dev; - feature_vsec_dev->resource = res; - feature_vsec_dev->num_resources = pfs->pfs_header.num_entries; feature_vsec_dev->priv_data = &tpmi_info->plat_info; feature_vsec_dev->priv_data_size =sizeof (tpmi_info->plat_info); feature_vsec_dev->ida = &intel_vsec_tpmi_ida;
include/linux/intel_vsec.h +3 -3
@@ -135,8 +135,6 @@ struct intel_vsec_platform_info {* struct intel_vsec_device - Auxbus specific device information * @auxdev: auxbus device struct for auxbus access * @dev: struct device associated with the device -* @resource: PCI discovery resources (BAR windows), one per discovery -* instance. Valid only when @src == INTEL_VSEC_DISC_PCI * @acpi_disc: ACPI discovery tables, each entry is two QWORDs * in little-endian format as defined by the PMT ACPI spec. * Valid only when @src == INTEL_VSEC_DISC_ACPI.
@@ -149,11 +147,12 @@ struct intel_vsec_platform_info {* @quirks: specified quirks * @base_addr: base address of entries (if specified) * @cap_id: the enumerated id of the vsec feature +* @resource: PCI discovery resources (BAR windows), one per discovery +* instance. Valid only when @src == INTEL_VSEC_DISC_PCI */ struct intel_vsec_device {struct auxiliary_device auxdev;struct device *dev; -struct resource *resource;u32 (*acpi_disc)[4 ];enum intel_vsec_disc_source src;struct ida *ida;
@@ -164,6 +163,7 @@ struct intel_vsec_device {unsigned long quirks;u64 base_addr;unsigned long cap_id; + struct resource resource[] __counted_by(num_resources); };/**
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 183/744 platform/x86/intel/vsec: free ACPI discovery data on early errors
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yousef Alhouseen <[email protected]>
[ Upstream commit 09b2ae290a241ce1f5f738fb65c35f449dcf663d ]
intel_vsec_add_dev() may attach an ACPI discovery table copy to the intel_vsec_device before passing ownership to intel_vsec_add_aux(). The normal auxiliary-device release path frees that copy, but the earliest intel_vsec_add_aux() failures free only the outer structure directly.
Route those direct frees through a common helper so acpi_disc is released consistently on the parent, xarray, and ID allocation failure paths.
--- drivers/platform/x86/intel/vsec.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-)
drivers/platform/x86/intel/vsec.c +12 -5
@@ -103,6 +103,12 @@ static void intel_vsec_remove_aux(void *data)auxiliary_device_uninit (data); } +static void intel_vsec_dev_free (struct intel_vsec_device *intel_vsec_dev) +{ +kfree (intel_vsec_dev->acpi_disc); +kfree (intel_vsec_dev); +} +static void intel_vsec_dev_release (struct device *dev) {struct intel_vsec_device *intel_vsec_dev =dev_to_ivdev (dev);
@@ -111,8 +117,7 @@ static void intel_vsec_dev_release(struct device *dev)ida_free (intel_vsec_dev->ida, intel_vsec_dev->auxdev.id); -kfree (intel_vsec_dev->acpi_disc); -kfree (intel_vsec_dev); +intel_vsec_dev_free (intel_vsec_dev); } static const struct vsec_feature_dependency *
@@ -218,20 +223,22 @@ int intel_vsec_add_aux(struct device *parent,struct auxiliary_device *auxdev = &intel_vsec_dev->auxdev;int ret, id; -if (!parent) +if (!parent) { +intel_vsec_dev_free (intel_vsec_dev);return -EINVAL ; + } ret =xa_alloc (&auxdev_array, &intel_vsec_dev->id, intel_vsec_dev,PMT_XA_LIMIT ,GFP_KERNEL );if (ret <0 ) { -kfree (intel_vsec_dev); +intel_vsec_dev_free (intel_vsec_dev);return ret; } id =ida_alloc (intel_vsec_dev->ida,GFP_KERNEL );if (id <0 ) {xa_erase (&auxdev_array, intel_vsec_dev->id); -kfree (intel_vsec_dev); +intel_vsec_dev_free (intel_vsec_dev);return id; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 184/744 platform/x86: asus-wmi: temporarily revert to setting a charge limit
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Denis Benato <[email protected]>
[ Upstream commit 78bf392ba77dd8b2a25656e489449d2f91cfd1eb ]
A userspace regression has been observed leaving the battery charging threshold unconfigured, so while the fix is being shipped revert the change keeping the infrastructure in place to return to the preferred behaviour as soon as it's appropriate to do.
--- drivers/platform/x86/asus-wmi.c | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-)
drivers/platform/x86/asus-wmi.c +23 -3
@@ -1566,6 +1566,8 @@ static DEVICE_ATTR_RW(charge_control_end_threshold);static int asus_wmi_battery_add (struct power_supply *battery,struct acpi_battery_hook *hook) { +int ret, rv; +/* The WMI method does not provide a way to specific a battery, so we * just assume it is the first battery. * Note: On some newer ASUS laptops (Zenbook UM431DA), the primary/first
@@ -1583,12 +1585,30 @@ static int asus_wmi_battery_add(struct power_supply *battery, struct acpi_batter/* The charge threshold is only reset when the system is power cycled, * and we can't read the current threshold, however the majority of -* platforms retains it, therefore signal the threshold as unknown -* until user explicitly sets it to a new value. +* platforms retains it. +* +* Setting a negative value would signal the threshold as unknown +* until user explicitly sets it to a new value, however to avoid +* regressing userspace, we initialize it to a value of 100. */ - charge_end_threshold =-1 ; + charge_end_threshold =100 ; + ret =asus_wmi_set_devstate (ASUS_WMI_DEVID_RSOC , charge_end_threshold, &rv); +if (ret) { +pr_err ("Failed to reset battery charge threshold\n" ); + goto asus_wmi_battery_add_err; + } + +if (rv !=1 ) { +pr_err ("Error in battery charge threshold reset\n" ); + ret = -EIO ; + goto asus_wmi_battery_add_err; + }return 0 ; +asus_wmi_battery_add_err: +device_remove_file (&battery->dev, + &dev_attr_charge_control_end_threshold); +return ret; }static int asus_wmi_battery_remove (struct power_supply *battery,struct acpi_battery_hook *hook)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 185/744 firewire: net: Fix fragmented datagram reassembly
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ruoyu Wang <[email protected]>
[ Upstream commit d52a13adbb8ccbab99cd3bad36804e87d8b5c052 ]
fwnet_frag_new() keeps a sorted list of received fragments for a partial datagram. When a new fragment is adjacent to an existing fragment, the code checks whether the new fragment also closes the gap to the next or previous list entry.
Those neighbor lookups currently assume that the current fragment always has a real next or previous fragment. At a list edge, the next or previous entry is the list head, not a struct fwnet_fragment_info.
The gap checks also compare against the old edge of the current fragment instead of the edge after adding the new fragment. As a result, a fragment that bridges two existing ranges may leave two adjacent ranges unmerged, so fwnet_pd_is_complete() can miss a complete datagram.
Check for the list head before looking up the neighboring fragment, and compare the neighbor against the new fragment's far edge when deciding whether to merge all three ranges.
This issue was found by a static analysis checker and confirmed by manual source review.
--- drivers/firewire/net.c | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-)
drivers/firewire/net.c +21 -18
@@ -298,31 +298,34 @@ static struct fwnet_fragment_info *fwnet_frag_new(if (fi->offset + fi->len == offset) {/* The new fragment can be tacked on to the end */ /* Did the new fragment plug a hole? */ - fi2 =list_entry (fi->fi_link.next, - struct fwnet_fragment_info, fi_link); -if (fi->offset + fi->len == fi2->offset) { -/* glue fragments together */ - fi->len += len + fi2->len; -list_del (&fi2->fi_link); -kfree (fi2); - }else { - fi->len += len; +if (!list_is_last (&fi->fi_link, &pd->fi_list)) { + fi2 =list_next_entry (fi, fi_link); +if (offset + len == fi2->offset) { +/* glue fragments together */ + fi->len += len + fi2->len; +list_del (&fi2->fi_link); +kfree (fi2); + +return fi; + } } + fi->len += len;return fi; }if (offset + len == fi->offset) {/* The new fragment can be tacked on to the beginning */ /* Did the new fragment plug a hole? */ - fi2 =list_entry (fi->fi_link.prev, - struct fwnet_fragment_info, fi_link); -if (fi2->offset + fi2->len == fi->offset) { -/* glue fragments together */ - fi2->len += fi->len + len; -list_del (&fi->fi_link); -kfree (fi); - -return fi2; +if (!list_is_first (&fi->fi_link, &pd->fi_list)) { + fi2 =list_prev_entry (fi, fi_link); +if (fi2->offset + fi2->len == offset) { +/* glue fragments together */ + fi2->len += fi->len + len; +list_del (&fi->fi_link); +kfree (fi); + +return fi2; + } } fi->offset = offset; fi->len += len;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 186/744 wifi: ath12k: Fix low MLO RX throughput on WCN7850
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yingying Tang <[email protected]>
[ Upstream commit a2fe9dc70f3b8d5716fbcfed5fbfb9cf3948d402 ]
Commit [1] introduced a regression causing severely degraded MLO RX throughput on WCN7850.
On WCN7850, there is only a single ar instance, but MLO uses two link IDs. ath12k_dp_peer->hw_links[] is indexed using ar->hw_link_id, which causes both MLO link IDs to be stored at the same index.
As a result, an incorrect link ID is assigned to MSDUs in ath12k_dp_rx_deliver_msdu(), leading to severe MLO RX throughput loss.
Different chipsets identify the per-MSDU link differently:
- On QCN9274 / IPQ5332, the host owns multiple ar instances and the per-MSDU hw_link_id from the RX descriptor maps cleanly through dp_peer->hw_links[hw_link_id] to the IEEE link_id.
- On single-ar chipsets like WCN7850 / QCC2072, there is only one ar
instance for both MLO links, so dp_peer->hw_links[] has just one
valid slot and cannot be used to distinguish the two links. To
resolve the link, walk dp_peer->link_peers[] and match by
rxcb->peer_id, which on the link_peer side identifies the link
peer for the MSDU.Add a new hw_op set_rx_link_id() so each chipset resolves the link on the RX fast path using whatever signal it actually has, and let the op itself decide whether to populate rx_status::link_valid and rx_status::link_id:
QCN9274 / IPQ5332 : always derive link_id from
dp_peer->hw_links[rxcb->hw_link_id] and set
link_valid. WCN7850 / QCC2072 : walk the link_peers[] of dp_peer to find the
link_peer whose peer_id matches rxcb->peer_id, and set link_valid only when a match is found. Otherwise leave link_valid clear so that mac80211 can fall back to its own link resolution path (via addr2 / deflink).
For WCN7850 / QCC2072, walking dp_peer->link_peers[] is bounded by the number of links actually populated, so introduce a link_peers_map bitmap (unsigned long) in struct ath12k_dp_peer that tracks populated slots and use for_each_set_bit() to iterate. Non-MLO clients hit one slot, current MLO clients hit two; the full ATH12K_NUM_MAX_LINKS array is never scanned. The bitmap is maintained with WRITE_ONCE() on the write side (under dp_hw->peer_lock) paired with READ_ONCE() on both the lockless RX read side and the write-side RMW for KCSAN correctness.
Also guard the dp_peer dereference in ath12k_mac_peer_cleanup_all() with a NULL check, since peer->dp_peer can be NULL for self-peers or peers not yet fully assigned, the pre-existing rcu_assign_pointer() call there had the same latent issue.
This restores the correct link ID on WCN7850 without changing the QCN9274 / IPQ5332 data path, which keeps its O(1) hw_links[] indexing.
Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c5-00302-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.115823.3
--- drivers/net/wireless/ath/ath12k/dp_peer.c | 4 +++ drivers/net/wireless/ath/ath12k/dp_peer.h | 1 + drivers/net/wireless/ath/ath12k/dp_rx.c | 7 ++-- drivers/net/wireless/ath/ath12k/hw.h | 16 +++++++++ drivers/net/wireless/ath/ath12k/mac.c | 10 ++++-- drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c | 33 +++++++++++++++++++ drivers/net/wireless/ath/ath12k/wifi7/dp_rx.h | 6 ++++ drivers/net/wireless/ath/ath12k/wifi7/hw.c | 3 ++ 8 files changed, 73 insertions(+), 7 deletions(-)
drivers/net/wireless/ath/ath12k/dp_peer.c +4 -0
@@ -570,6 +570,8 @@ int ath12k_dp_link_peer_assign(struct ath12k_dp *dp, struct ath12k_dp_hw *dp_hw, peerid_index =ath12k_dp_peer_get_peerid_index (dp, peer->peer_id);rcu_assign_pointer (dp_peer->link_peers[peer->link_id], peer); +WRITE_ONCE (dp_peer->link_peers_map, +READ_ONCE (dp_peer->link_peers_map) |BIT (peer->link_id));rcu_assign_pointer (dp_hw->dp_peers[peerid_index], dp_peer);
@@ -632,6 +634,8 @@ void ath12k_dp_link_peer_unassign(struct ath12k_dp *dp, struct ath12k_dp_hw *dp_ peerid_index =ath12k_dp_peer_get_peerid_index (dp, peer->peer_id);rcu_assign_pointer (dp_peer->link_peers[peer->link_id],NULL ); +WRITE_ONCE (dp_peer->link_peers_map, +READ_ONCE (dp_peer->link_peers_map) & ~BIT (peer->link_id));rcu_assign_pointer (dp_hw->dp_peers[peerid_index],NULL );
drivers/net/wireless/ath/ath12k/dp_peer.h +1 -0
@@ -140,6 +140,7 @@ struct ath12k_dp_peer {/* Info used in MMIC verification of * RX fragments */ struct ieee80211_key_conf *keys[WMI_MAX_KEY_INDEX +1 ]; +unsigned long link_peers_map;struct ath12k_dp_link_peer __rcu *link_peers[ATH12K_NUM_MAX_LINKS ];struct ath12k_reoq_buf reoq_bufs[IEEE80211_NUM_TIDS +1 ];struct ath12k_dp_rx_tid rx_tid[IEEE80211_NUM_TIDS +1 ];
drivers/net/wireless/ath/ath12k/dp_rx.c +3 -4
@@ -1344,10 +1344,9 @@ void ath12k_dp_rx_deliver_msdu(struct ath12k_pdev_dp *dp_pdev, struct napi_struc pubsta = peer ? peer->sta :NULL ; -if (pubsta && pubsta->valid_links) { - status->link_valid =1 ; - status->link_id = peer->hw_links[rxcb->hw_link_id]; - } + status->link_valid =0 ; +if (pubsta && pubsta->valid_links) +ath12k_hw_set_rx_link_id (dp->hw_params, peer, rxcb, status); ath12k_dbg(dp->ab, ATH12K_DBG_DATA, "rx skb %p len %u peer %pM %d %s sn %u %s%s%s%s%s%s%s%s%s%s rate_idx %u vht_nss %u freq %u band %u flag 0x%x fcs-err %i mic-err %i amsdu-more %i\n",
drivers/net/wireless/ath/ath12k/hw.h +16 -0
@@ -13,6 +13,10 @@#include "wmi.h" #include "hal.h" +struct ath12k_dp_peer ; +struct ath12k_skb_rxcb ; +struct ieee80211_rx_status ; +/* Target configuration defines */ /* Num VDEVS per radio */
@@ -224,6 +228,9 @@ struct ath12k_hw_ops {bool (*dp_srng_is_tx_comp_ring)(int ring_num);bool (*is_frame_link_agnostic)(struct ath12k_link_vif *arvif,struct ieee80211_mgmt *mgmt); +void (*set_rx_link_id)(struct ath12k_dp_peer *dp_peer, +struct ath12k_skb_rxcb *rxcb, +struct ieee80211_rx_status *status); }; static inline
@@ -254,6 +261,15 @@ static inline int ath12k_hw_mac_id_to_srng_id(const struct ath12k_hw_params *hw,return 0 ; } +static inline void ath12k_hw_set_rx_link_id (const struct ath12k_hw_params *hw, +struct ath12k_dp_peer *dp_peer, +struct ath12k_skb_rxcb *rxcb, +struct ieee80211_rx_status *status) +{ +if (hw->hw_ops->set_rx_link_id) + hw->hw_ops->set_rx_link_id (dp_peer, rxcb, status); +} +struct ath12k_fw_ie {__le32 id;__le32 len;
drivers/net/wireless/ath/ath12k/mac.c +7 -3
@@ -1234,9 +1234,13 @@ void ath12k_mac_peer_cleanup_all(struct ath12k *ar)/* cleanup dp peer */ spin_lock_bh (&dp_hw->peer_lock); dp_peer = peer->dp_peer; - peerid_index =ath12k_dp_peer_get_peerid_index (dp, peer->peer_id); -rcu_assign_pointer (dp_peer->link_peers[peer->link_id],NULL ); -rcu_assign_pointer (dp_hw->dp_peers[peerid_index],NULL ); +if (dp_peer) { + peerid_index =ath12k_dp_peer_get_peerid_index (dp, peer->peer_id); +rcu_assign_pointer (dp_peer->link_peers[peer->link_id],NULL ); +WRITE_ONCE (dp_peer->link_peers_map, +READ_ONCE (dp_peer->link_peers_map) & ~BIT (peer->link_id)); +rcu_assign_pointer (dp_hw->dp_peers[peerid_index],NULL ); + }spin_unlock_bh (&dp_hw->peer_lock);ath12k_dp_link_peer_rhash_delete (dp, peer);
drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c +33 -0
@@ -5,6 +5,7 @@*/ #include "dp_rx.h" +#include "../dp_peer.h" #include "../dp_tx.h" #include "../peer.h" #include "hal_qcn9274.h"
@@ -2242,3 +2243,35 @@ ath12k_wifi7_dp_rxdesc_mpdu_valid(struct ath12k_base *ab,return tlv_tag ==HAL_RX_MPDU_START ; } + +void +ath12k_wifi7_dp_rx_set_link_id_qcn9274 (struct ath12k_dp_peer *dp_peer, +struct ath12k_skb_rxcb *rxcb, +struct ieee80211_rx_status *status) +{ + status->link_valid =1 ; + status->link_id = dp_peer->hw_links[rxcb->hw_link_id]; +} + +void +ath12k_wifi7_dp_rx_set_link_id_wcn7850 (struct ath12k_dp_peer *dp_peer, +struct ath12k_skb_rxcb *rxcb, +struct ieee80211_rx_status *status) +{ +struct ath12k_dp_link_peer *link_peer; +unsigned long links_map; +int i; + +RCU_LOCKDEP_WARN (!rcu_read_lock_held (), +"ath12k set rx link id called without rcu lock" ); + + links_map =READ_ONCE (dp_peer->link_peers_map); +for_each_set_bit (i, &links_map,ATH12K_NUM_MAX_LINKS ) { + link_peer =rcu_dereference (dp_peer->link_peers[i]); +if (link_peer && link_peer->peer_id == rxcb->peer_id) { + status->link_valid =1 ; + status->link_id = link_peer->link_id; +return ; + } + } +}
drivers/net/wireless/ath/ath12k/wifi7/dp_rx.h +6 -0
@@ -57,4 +57,10 @@ ath12k_wifi7_dp_rxdesc_mpdu_valid(struct ath12k_base *ab, struct hal_rx_desc *rx_desc);int ath12k_wifi7_dp_rx_tid_delete_handler (struct ath12k_base *ab,struct ath12k_dp_rx_tid_rxq *rx_tid); +void ath12k_wifi7_dp_rx_set_link_id_qcn9274 (struct ath12k_dp_peer *dp_peer, +struct ath12k_skb_rxcb *rxcb, +struct ieee80211_rx_status *status); +void ath12k_wifi7_dp_rx_set_link_id_wcn7850 (struct ath12k_dp_peer *dp_peer, +struct ath12k_skb_rxcb *rxcb, +struct ieee80211_rx_status *status);#endif
drivers/net/wireless/ath/ath12k/wifi7/hw.c +3 -0
@@ -158,6 +158,7 @@ static const struct ath12k_hw_ops qcn9274_ops = { .get_ring_selector = ath12k_wifi7_hw_get_ring_selector_qcn9274, .dp_srng_is_tx_comp_ring = ath12k_wifi7_dp_srng_is_comp_ring_qcn9274, .is_frame_link_agnostic = ath12k_wifi7_is_frame_link_agnostic_qcn9274, + .set_rx_link_id = ath12k_wifi7_dp_rx_set_link_id_qcn9274, };static const struct ath12k_hw_ops wcn7850_ops = {
@@ -168,6 +169,7 @@ static const struct ath12k_hw_ops wcn7850_ops = { .get_ring_selector = ath12k_wifi7_hw_get_ring_selector_wcn7850, .dp_srng_is_tx_comp_ring = ath12k_wifi7_dp_srng_is_comp_ring_wcn7850, .is_frame_link_agnostic = ath12k_wifi7_is_frame_link_agnostic_wcn7850, + .set_rx_link_id = ath12k_wifi7_dp_rx_set_link_id_wcn7850, };static const struct ath12k_hw_ops qcc2072_ops = {
@@ -178,6 +180,7 @@ static const struct ath12k_hw_ops qcc2072_ops = { .get_ring_selector = ath12k_wifi7_hw_get_ring_selector_wcn7850, .dp_srng_is_tx_comp_ring = ath12k_wifi7_dp_srng_is_comp_ring_wcn7850, .is_frame_link_agnostic = ath12k_wifi7_is_frame_link_agnostic_wcn7850, + .set_rx_link_id = ath12k_wifi7_dp_rx_set_link_id_wcn7850, };#define ATH12K_TX_RING_MASK_0 0x1
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 187/744 wifi: ath6kl: fix OOB read from firmware num_msg in TX complete handler
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tristan Madani <[email protected]>
[ Upstream commit 3a21c89215cc18f1a97c5e5bfd1da6d4f3d44495 ]
The firmware-controlled num_msg field (u8, 0-255) drives the loop in ath6kl_wmi_tx_complete_event_rx() without validation against the buffer length. This allows out-of-bounds reads of up to 1020 bytes past the WMI event buffer when the firmware sends an inflated num_msg.
Add a check that the buffer is large enough to hold the fixed struct and the num_msg variable-length entries.
--- drivers/net/wireless/ath/ath6kl/wmi.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
drivers/net/wireless/ath/ath6kl/wmi.c +12 -0
@@ -484,6 +484,18 @@ static int ath6kl_wmi_tx_complete_event_rx(u8 *datap, int len) evt = (struct wmi_tx_complete_event *) datap; +if (len <sizeof (*evt)) { +ath6kl_dbg (ATH6KL_DBG_WMI ,"tx complete: invalid len %d\n" , + len); +return -EINVAL ; + } + +if (len <sizeof (*evt) + evt->num_msg *sizeof (struct tx_complete_msg_v1 )) { +ath6kl_dbg (ATH6KL_DBG_WMI ,"tx complete: invalid len %d for %u msgs\n" , + len, evt->num_msg); +return -EINVAL ; + } +ath6kl_dbg (ATH6KL_DBG_WMI ,"comp: %d %d %d\n" , evt->num_msg, evt->msg_len, evt->msg_type);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 188/744 wifi: ath6kl: fix OOB read from firmware IE lengths in connect event
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tristan Madani <[email protected]>
[ Upstream commit 6b47b29730de3232b919d8362749f6814c5f2a33 ]
The firmware-controlled beacon_ie_len, assoc_req_len, and assoc_resp_len fields in ath6kl_wmi_connect_event_rx() are not validated against the buffer length. Their sum (up to 765) can exceed the actual WMI event data, causing out-of-bounds reads during IE parsing and state corruption of wmi->is_wmm_enabled.
Add a check that the total IE length fits within the buffer.
--- drivers/net/wireless/ath/ath6kl/wmi.c | 8 ++++++++ 1 file changed, 8 insertions(+)
drivers/net/wireless/ath/ath6kl/wmi.c +8 -0
@@ -874,6 +874,14 @@ static int ath6kl_wmi_connect_event_rx(struct wmi *wmi, u8 *datap, int len, ev = (struct wmi_connect_event *) datap; +if (len <sizeof (*ev) + ev->beacon_ie_len + + ev->assoc_req_len + ev->assoc_resp_len) { +ath6kl_dbg (ATH6KL_DBG_WMI , +"connect event: IE lengths %u+%u+%u exceed buffer %d\n" , + ev->beacon_ie_len, ev->assoc_req_len, + ev->assoc_resp_len, len); +return -EINVAL ; + }if (vif->nw_type ==AP_NETWORK ) {/* AP mode start/STA connected event */ struct net_device *dev = vif->ndev;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 189/744 wifi: carl9170: bound memcpy length in cmd callback to prevent OOB read
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tristan Madani <[email protected]>
[ Upstream commit 4cde55b2feff9504d1f993ab80e84e7ccb62791c ]
When the firmware sends a command response with a length mismatch, carl9170_cmd_callback() logs the mismatch and calls carl9170_restart() but then falls through to memcpy(ar->readbuf, buffer + 4, len - 4). Since len comes from the firmware and can exceed ar->readlen, this copies more data than the readbuf was allocated for.
Bound the memcpy to min(len - 4, ar->readlen) so that the response is still completed -- avoiding repeated restarts from queued garbage -- while preventing an overread past the response buffer.
--- drivers/net/wireless/ath/carl9170/rx.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/net/wireless/ath/carl9170/rx.c +2 -1
@@ -150,7 +150,8 @@ static void carl9170_cmd_callback(struct ar9170 *ar, u32 len, void *buffer)spin_lock (&ar->cmd_lock);if (ar->readbuf) {if (len >=4 ) -memcpy (ar->readbuf, buffer +4 , len -4 ); +memcpy (ar->readbuf, buffer +4 , +min_t (u32, len -4 , ar->readlen)); ar->readbuf =NULL ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 190/744 wifi: carl9170: fix OOB read from off-by-two in TX status handler
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tristan Madani <[email protected]>
[ Upstream commit a3f42f1049ad80c65560d2b078ad426c3134f78d ]
The bounds check in carl9170_tx_process_status() usesi > ((cmd->hdr.len / 2) + 1) which is off by two, allowing 2 extra iterations past valid _tx_status entries when the firmware- controlled hdr.ext exceeds hdr.len/2. Fix by using the correct comparison i >= (cmd->hdr.len / 2).
--- drivers/net/wireless/ath/carl9170/tx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/wireless/ath/carl9170/tx.c +1 -1
@@ -692,7 +692,7 @@ void carl9170_tx_process_status(struct ar9170 *ar,unsigned int i;for (i =0 ; i < cmd->hdr.ext; i++) { -if (WARN_ON (i > ((cmd->hdr.len /2 ) +1 ))) { +if (WARN_ON (i >= (cmd->hdr.len /2 ))) {print_hex_dump_bytes ("UU:" ,DUMP_PREFIX_NONE , (void *) cmd, cmd->hdr.len +4 );break ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 191/744 wifi: carl9170: fix buffer overflow in rx_stream failover path
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tristan Madani <[email protected]>
[ Upstream commit a1a21995c2e1cc2ca6b2226cfe4f5f018370182a ]
The failover continuation in carl9170_rx_stream() copies the full tlen from the second USB transfer instead of capping at rx_failover_missing bytes. When both transfers are near maximum size, the total exceeds the 65535-byte failover SKB, triggering skb_over_panic.
Limit the copy size to the missing byte count.
--- drivers/net/wireless/ath/carl9170/rx.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/net/wireless/ath/carl9170/rx.c +3 -1
@@ -918,7 +918,9 @@ static void carl9170_rx_stream(struct ar9170 *ar, void *buf, unsigned int len) } } -skb_put_data (ar->rx_failover, tbuf, tlen); +skb_put_data (ar->rx_failover, tbuf, + min_t(unsigned int, tlen, + ar->rx_failover_missing)); ar->rx_failover_missing -= tlen;if (ar->rx_failover_missing <=0 ) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 192/744 btrfs: declare btrfs_ioctl_search_args_v2::buf as __u8
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: You-Kai Zheng <[email protected]>
[ Upstream commit b95181f3929ff98949fa9460ca93eccebbf2d7fc ]
The variable-sized buffer buf in struct btrfs_ioctl_search_args_v2 is declared as __u64[], but it holds a packed byte stream of search results, where all offsets into the buffer are in bytes.
Declaring buf as __u64[] makes it easy for user space to write incorrect pointer arithmetic: adding a byte offset directly to a __u64 pointer scales the offset by 8, landing at byte position offset*8 instead of offset.
This recently caused an infinite loop in btrfs-progs: the accessor read all-zero data from misaddressed items, which fed zeroed search keys back into the ioctl loop and spun forever. The issue was worked around at the time by disabling TREE_SEARCH_V2 entirely in btrfs-progs (d73e69824854:
"btrfs-progs: temporarily disable usage of v2 of search tree ioctl").
The kernel side already treats buf as a byte buffer, so change the declaration to __u8[] to match the actual semantics and prevent similar misuse in user space. The change is ABI compatible: both the structure size and alignment are unchanged.
--- include/uapi/linux/btrfs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
include/uapi/linux/btrfs.h +1 -1
@@ -598,7 +598,7 @@ struct btrfs_ioctl_search_args_v2 {__u64 buf_size;/* in - size of buffer * out - on EOVERFLOW: needed size * to store item */ -__u64 buf[];/* out - found items */ +__u8 buf[];/* out - found items */ };/* With a @src_length of zero, the range from @src_offset->EOF is cloned! */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 193/744 btrfs: fix u32 to s64 type conversion in dirty_metadata_bytes accounting
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dave Chen <[email protected]>
[ Upstream commit 8b5a09ceb61b18b1f0797cd30a549d7dc85d8d50 ]
The percpu_counter dirty_metadata_bytes is updated by negating eb->len and passing it to percpu_counter_add_batch(), whose amount parameter is s64. Since commit 84cda1a6087d ("btrfs: cache folio size and shift in extent_buffer"), eb->len is u32. The u32 result of -eb->len, when widened to the s64 parameter, becomes a large positive value instead of the intended negative value. For eb->len == 16384 the counter adds +4294950912 instead of subtracting 16384.
The counter therefore grows on every metadata writeback instead of shrinking by the extent buffer size, permanently exceeding BTRFS_DIRTY_METADATA_THRESH and causing __btrfs_btree_balance_dirty() to trigger balance_dirty_pages_ratelimited() unconditionally, adding unnecessary writeback pressure.
Cast eb->len to s64 before negation at both call sites so the subtraction is performed in signed 64-bit arithmetic.
--- fs/btrfs/extent_io.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
fs/btrfs/extent_io.c +2 -2
@@ -1963,7 +1963,7 @@ static noinline_for_stack bool lock_extent_buffer_for_io(struct extent_buffer *ebtrfs_set_header_flag (eb,BTRFS_HEADER_FLAG_WRITTEN );percpu_counter_add_batch (&fs_info->dirty_metadata_bytes, - -eb->len, + -(s64 )eb->len, fs_info->dirty_metadata_batch); ret = true; }else {
@@ -3778,7 +3778,7 @@ void btrfs_clear_buffer_dirty(struct btrfs_trans_handle *trans,return ;buffer_tree_clear_mark (eb,PAGECACHE_TAG_DIRTY ); -percpu_counter_add_batch (&fs_info->dirty_metadata_bytes, -eb->len, +percpu_counter_add_batch (&fs_info->dirty_metadata_bytes, -(s64 )eb->len, fs_info->dirty_metadata_batch);for (int i =0 ; i <num_extent_folios (eb); i++) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 194/744 btrfs: dont propagate EXTENT_FLAG_LOGGING to split extent maps
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Leo Martins <[email protected]>
[ Upstream commit 5eff4d5b17fa1950e80bfd1ba43dc0699e61a644 ]
When btrfs_drop_extent_map_range() splits an extent map, the new split maps inherit the original map's flags through a local 'flags' variable. Commit f86f7a75e2fb ("btrfs: use the flags of an extent map to identify the compression type") changed the EXTENT_FLAG_LOGGING clearing to operate on em->flags instead of that local 'flags' copy, so a split of an extent map that is currently being logged wrongly inherits EXTENT_FLAG_LOGGING.
The flag is then never cleared on the split, and when it is freed while still on the inode's modified_extents list (for example by the extent map shrinker) it trips the WARN_ON(!list_empty(&em->list)) in btrfs_free_extent_map() and leads to a use-after-free.
Clear EXTENT_FLAG_LOGGING from the local 'flags' copy used for the splits and only clear EXTENT_FLAG_PINNED from em->flags, restoring the behaviour prior to f86f7a75e2fb.
--- fs/btrfs/extent_map.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
fs/btrfs/extent_map.c +2 -2
@@ -866,13 +866,13 @@ void btrfs_drop_extent_map_range(struct btrfs_inode *inode, u64 start, u64 end, goto next; } - flags = em->flags;/* * In case we split the extent map, we want to preserve the * EXTENT_FLAG_LOGGING flag on our extent map, but we don't want * it on the new extent maps. */ - em->flags &= ~(EXTENT_FLAG_PINNED |EXTENT_FLAG_LOGGING ); + flags = em->flags & ~EXTENT_FLAG_LOGGING ; + em->flags &= ~EXTENT_FLAG_PINNED ; modified = !list_empty (&em->list);/*
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 195/744 btrfs: free mapping node on duplicate reloc root insert
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guanghui Yang <[email protected]>
[ Upstream commit 6a8269b6459ed870a8156c106a0f597383907872 ]
__add_reloc_root() allocates a mapping_node before inserting it into rc->reloc_root_tree. If rb_simple_insert() finds an existing entry, it returns the existing rb_node and leaves the newly allocated node unlinked.
The error path then returns -EEXIST without freeing the new node. Since the node was never inserted into reloc_root_tree, the later cleanup in put_reloc_control() cannot find it either.
Free the newly allocated node before returning -EEXIST.
The callers currently assert that -EEXIST should not happen, so this is a defensive cleanup for an unexpected duplicate insert path. If the path is ever reached, the local allocation should still be released.
--- fs/btrfs/relocation.c | 1 + 1 file changed, 1 insertion(+)
fs/btrfs/relocation.c +1 -0
@@ -497,6 +497,7 @@ static int __add_reloc_root(struct btrfs_root *root)btrfs_err (fs_info,"Duplicate root found for start=%llu while inserting into relocation tree" , node->bytenr); +kfree (node);return -EEXIST ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 196/744 ASoC: tas2781: bound firmware description string parsing
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pengpeng Hou <[email protected]>
[ Upstream commit bc889dfcea9294a1eae7f8e2f3573a90764ae4d0 ]
The TAS2781 firmware parser reads several variable-length description strings with strlen() before checking that the string terminator is present inside the firmware blob. A malformed firmware image without a NUL terminator can therefore make the parser walk past the end of the firmware buffer before the later size checks run.
Add a small bounded string-length helper and use it for all description fields that are parsed from the firmware buffer. Keep the existing size checks for the fixed bytes that follow each string.
--- sound/soc/codecs/tas2781-fmwlib.c | 63 ++++++++++++++++++++++++++++--- 1 file changed, 57 insertions(+), 6 deletions(-)
sound/soc/codecs/tas2781-fmwlib.c +57 -6
@@ -12,6 +12,7 @@#include <linux/i2c.h> #include <linux/init.h> #include <linux/interrupt.h> +#include <linux/limits.h> #include <linux/module.h> #include <linux/of.h> #include <linux/of_irq.h>
@@ -1099,13 +1100,42 @@ static int tasdevice_load_block_kernel(return 0 ; } +static int tasdevice_fw_strnlen (const struct firmware *fmw,int offset) +{ +const u8 *start; +const u8 *nul; +size_t remaining; +size_t len; + +if (offset <0 || offset >= fmw->size) +return -EINVAL ; + + start = fmw->data + offset; + remaining = fmw->size - offset; + nul =memchr (start,'\0' , remaining); +if (!nul) +return -EINVAL ; + + len = nul - start; +if (len >INT_MAX ) +return -EOVERFLOW ; + +return len; +} +static int fw_parse_variable_hdr (struct tasdevice_priv *tas_priv,struct tasdevice_dspfw_hdr *fw_hdr,const struct firmware *fmw,int offset) {const unsigned char *buf = fmw->data; -int len =strlen ((char *)&buf[offset]); +int len; + len =tasdevice_fw_strnlen (fmw, offset); +if (len <0 ) { +dev_err (tas_priv->dev,"%s: Description error\n" , __func__); + offset = len; + goto out; + } len++;if (offset + len +8 > fmw->size) {
@@ -1237,7 +1267,12 @@ static int fw_parse_data(struct tasdevice_fw *tas_fmw,memcpy (img_data->name, &data[offset],64 ); offset +=64 ; - n =strlen ((char *)&data[offset]); + n =tasdevice_fw_strnlen (fmw, offset); +if (n <0 ) { +dev_err (tas_fmw->dev,"%s: Description error\n" , __func__); + offset = n; + goto out; + } n++;if (offset + n +2 > fmw->size) {dev_err (tas_fmw->dev,"%s: Description error\n" , __func__);
@@ -1308,7 +1343,12 @@ static int fw_parse_program_data(struct tasdevice_priv *tas_priv, } offset +=64 ; - n =strlen ((char *)&buf[offset]); + n =tasdevice_fw_strnlen (fmw, offset); +if (n <0 ) { +dev_err (tas_priv->dev,"Description err\n" ); + offset = n; + goto out; + }/* skip '\0' and 5 unused bytes */ n +=6 ;if (offset + n > fmw->size) {
@@ -1371,7 +1411,12 @@ static int fw_parse_configuration_data(memcpy (config->name, &data[offset],64 ); offset +=64 ; - n =strlen ((char *)&data[offset]); + n =tasdevice_fw_strnlen (fmw, offset); +if (n <0 ) { +dev_err (tas_priv->dev,"Description err\n" ); + offset = n; + goto out; + } n +=15 ;if (offset + n > fmw->size) {dev_err (tas_priv->dev,"Description err\n" );
@@ -2133,7 +2178,8 @@ static int fw_parse_calibration_data(struct tasdevice_priv *tas_priv, {struct tasdevice_calibration *calibration;unsigned char *data = (unsigned char *)fmw->data; -unsigned int i, n; +unsigned int i; +int n;if (offset +2 > fmw->size) {dev_err (tas_priv->dev,"%s: Calibrations error\n" , __func__);
@@ -2165,7 +2211,12 @@ static int fw_parse_calibration_data(struct tasdevice_priv *tas_priv, calibration = &(tas_fmw->calibrations[i]); offset +=64 ; - n =strlen ((char *)&data[offset]); + n =tasdevice_fw_strnlen (fmw, offset); +if (n <0 ) { +dev_err (tas_priv->dev,"Description err\n" ); + offset = n; + goto out; + }/* skip '\0' and 2 unused bytes */ n +=3 ;if (offset + n > fmw->size) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 197/744 ASoC: sun4i-codec: Set quirks.playback_only for H616 codec
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chen-Yu Tsai <[email protected]>
[ Upstream commit d9e96f859de3ea3e99bce927a988449a1816483c ]
The H616 codec does not have capture capabilities. Set the .playback_only quirks flag to denote this.
This was somehow missing from the original driver patch, even though the patch prior to it in the series added this quirk.
--- sound/soc/sunxi/sun4i-codec.c | 1 + 1 file changed, 1 insertion(+)
sound/soc/sunxi/sun4i-codec.c +1 -0
@@ -2237,6 +2237,7 @@ static const struct sun4i_codec_quirks sun50i_h616_codec_quirks = { .reg_dac_fifoc = REG_FIELD(SUN50I_H616_CODEC_DAC_FIFOC, 0, 31), .reg_dac_txdata = SUN8I_H3_CODEC_DAC_TXDATA, .has_reset = true, + .playback_only = true, .dma_max_burst = SUN4I_DMA_MAX_BURST, };
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 198/744 iommu/amd: Fix IRQ unsafe locking in gdom allocation
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tycho Andersen (AMD) <[email protected]>
[ Upstream commit 0db3a430d9681fdb29890bef6934cd89cd1745d0 ]
Lockdep complains:
[ 259.410489] =====================================================
[ 259.417287] WARNING: HARDIRQ-safe -> HARDIRQ-unsafe lock order detected
[ 259.424667] 7.0.0-g51db1d8d2113 #54 Not tainted
[ 259.429718] -----------------------------------------------------
[ 259.436516] qemu-system-x86/10143 [HC0[0]:SC0[0]:HE0:SE1] is trying to acquire:
[ 259.444670] ff3b2b1c60305170 (&xa->xa_lock#25){+.+.}-{3:3}, at: __domain_flush_pages+0x17c/0x4b0
[ 259.454485]
and this task is already holding:
[ 259.460991] ff3b2b1c98504cc0 (&domain->lock){-.-.}-{3:3}, at: amd_iommu_iotlb_sync+0x25/0x60
[ 259.470408] which would create a new lock dependency:
[ 259.476041] (&domain->lock){-.-.}-{3:3} -> (&xa->xa_lock#25){+.+.}-{3:3}
[ 259.483615]
but this new dependency connects a HARDIRQ-irq-safe lock:
[ 259.492447] (&domain->lock){-.-.}-{3:3}
[ 259.492449]
... which became HARDIRQ-irq-safe at:
[ 259.503705] lock_acquire+0xb6/0x2e0
[ 259.507790] _raw_spin_lock_irqsave+0x3e/0x60
[ 259.512748] amd_iommu_flush_iotlb_all+0x20/0x50
[ 259.517996] iommu_dma_free_iova.isra.0+0x1b8/0x1e0
[ 259.523534] __iommu_dma_unmap+0xc2/0x140
[ 259.528100] iommu_dma_unmap_phys+0x55/0xc0
[ 259.532863] dma_unmap_phys+0x274/0x2e0
[ 259.537238] dma_unmap_page_attrs+0x17/0x30
[ 259.542000] nvme_unmap_data+0x13e/0x280
[ 259.546473] nvme_pci_complete_batch+0x45/0x70
[ 259.551524] nvme_irq+0x83/0x90
[ 259.555123] __handle_irq_event_percpu+0x92/0x360
[ 259.560466] handle_irq_event+0x39/0x80
[ 259.564841] handle_edge_irq+0xb2/0x1a0
[ 259.569214] __common_interrupt+0x4e/0x130
[ 259.573882] common_interrupt+0x88/0xa0
[ 259.578256] asm_common_interrupt+0x27/0x40
[ 259.583019] cpuidle_enter_state+0x119/0x5d0
[ 259.587877] cpuidle_enter+0x2e/0x50
[ 259.591962] do_idle+0x153/0x2c0
[ 259.595657] cpu_startup_entry+0x29/0x30
[ 259.600128] start_secondary+0x118/0x150
[ 259.604601] common_startup_64+0x13e/0x141
[ 259.609266]
to a HARDIRQ-irq-unsafe lock:
[ 259.615384] (&xa->xa_lock#25){+.+.}-{3:3}
[ 259.615386]
... which became HARDIRQ-irq-unsafe at:
[ 259.627039] ...
[ 259.627039] lock_acquire+0xb6/0x2e0
[ 259.633071] _raw_spin_lock+0x2f/0x50
[ 259.637250] amd_iommu_alloc_domain_nested+0x140/0x3c0
[ 259.643078] iommufd_hwpt_alloc+0x272/0x800 [iommufd]
[ 259.648813] iommufd_fops_ioctl+0x14e/0x200 [iommufd]
[ 259.654547] __x64_sys_ioctl+0x9d/0xf0
...Since amd_iommu_domain_flush_pages() necessarily holds domain->lock to do the flush, switch the allocation side in gdom_info_load_or_alloc_locked() to HARDIRQ-safe allocation. The IOMMU_DESTROY->free path has the same issue, so switch that path to HARDIRQ-safe locking as well.
--- drivers/iommu/amd/nested.c | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-)
drivers/iommu/amd/nested.c +18 -13
@@ -59,7 +59,9 @@ static int validate_gdte_nested(struct iommu_hwpt_amd_guest *gdte)return 0 ; } -static void *gdom_info_load_or_alloc_locked (struct xarray *xa,unsigned long index) +static void *gdom_info_load_or_alloc_locked (struct xarray *xa, +unsigned long index, +unsigned long *flags) {struct guest_domain_mapping_info *elm, *res;
@@ -67,13 +69,13 @@ static void *gdom_info_load_or_alloc_locked(struct xarray *xa, unsigned long indif (elm)return elm; -xa_unlock (xa); +xa_unlock_irqrestore (xa, *flags); elm = kzalloc_obj(struct guest_domain_mapping_info); -xa_lock (xa); +xa_lock_irqsave (xa, *flags);if (!elm)return ERR_PTR (-ENOMEM ); - res =__xa_cmpxchg (xa, index,NULL , elm,GFP_KERNEL ); + res =__xa_cmpxchg (xa, index,NULL , elm,GFP_ATOMIC );if (xa_is_err (res)) res =ERR_PTR (xa_err (res));
@@ -95,6 +97,7 @@ amd_iommu_alloc_domain_nested(struct iommufd_viommu *viommu, u32 flags, const struct iommu_user_data *user_data) {int ret; +unsigned long irqflags;struct nested_domain *ndom;struct guest_domain_mapping_info *gdom_info; struct amd_iommu_viommu *aviommu = container_of(viommu, struct amd_iommu_viommu, core);
@@ -136,11 +139,12 @@ amd_iommu_alloc_domain_nested(struct iommufd_viommu *viommu, u32 flags,* keep track of the gDomID mapping. When the S2 is changed, the INVALIDATE_IOMMU_PAGES * command must be issued for each hDomID in the xarray. */ -xa_lock (&aviommu->gdomid_array); +xa_lock_irqsave (&aviommu->gdomid_array, irqflags); - gdom_info =gdom_info_load_or_alloc_locked (&aviommu->gdomid_array, ndom->gdom_id); + gdom_info =gdom_info_load_or_alloc_locked (&aviommu->gdomid_array, + ndom->gdom_id, &irqflags);if (IS_ERR (gdom_info)) { -xa_unlock (&aviommu->gdomid_array); +xa_unlock_irqrestore (&aviommu->gdomid_array, irqflags); ret =PTR_ERR (gdom_info); goto out_err; }
@@ -148,7 +152,7 @@ amd_iommu_alloc_domain_nested(struct iommufd_viommu *viommu, u32 flags,/* Check if gDomID exist */ if (refcount_inc_not_zero (&gdom_info->users)) { ndom->gdom_info = gdom_info; -xa_unlock (&aviommu->gdomid_array); +xa_unlock_irqrestore (&aviommu->gdomid_array, irqflags);pr_debug ("%s: Found gdom_id=%#x, hdom_id=%#x\n" , __func__, ndom->gdom_id, gdom_info->hdom_id);
@@ -161,7 +165,7 @@ amd_iommu_alloc_domain_nested(struct iommufd_viommu *viommu, u32 flags,if (gdom_info->hdom_id <=0 ) {__xa_cmpxchg (&aviommu->gdomid_array, ndom->gdom_id, gdom_info,NULL ,GFP_ATOMIC ); -xa_unlock (&aviommu->gdomid_array); +xa_unlock_irqrestore (&aviommu->gdomid_array, irqflags); ret = -ENOSPC ; goto out_err_gdom_info; }
@@ -169,7 +173,7 @@ amd_iommu_alloc_domain_nested(struct iommufd_viommu *viommu, u32 flags, ndom->gdom_info = gdom_info;refcount_set (&gdom_info->users,1 ); -xa_unlock (&aviommu->gdomid_array); +xa_unlock_irqrestore (&aviommu->gdomid_array, irqflags);pr_debug ("%s: Allocate gdom_id=%#x, hdom_id=%#x\n" , __func__, ndom->gdom_id, gdom_info->hdom_id);
@@ -257,14 +261,15 @@ static int nested_attach_device(struct iommu_domain *dom, struct device *dev,static void nested_domain_free (struct iommu_domain *dom) { +unsigned long irqflags;struct guest_domain_mapping_info *curr;struct nested_domain *ndom =to_ndomain (dom);struct amd_iommu_viommu *aviommu = ndom->viommu; -xa_lock (&aviommu->gdomid_array); +xa_lock_irqsave (&aviommu->gdomid_array, irqflags);if (!refcount_dec_and_test (&ndom->gdom_info->users)) { -xa_unlock (&aviommu->gdomid_array); +xa_unlock_irqrestore (&aviommu->gdomid_array, irqflags);return ; }
@@ -275,7 +280,7 @@ static void nested_domain_free(struct iommu_domain *dom) curr =__xa_cmpxchg (&aviommu->gdomid_array, ndom->gdom_id, ndom->gdom_info,NULL ,GFP_ATOMIC ); -xa_unlock (&aviommu->gdomid_array); +xa_unlock_irqrestore (&aviommu->gdomid_array, irqflags);if (WARN_ON (!curr ||xa_err (curr)))return ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 199/744 iommu/amd: Fix nested domain leak
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tycho Andersen (AMD) <[email protected]>
[ Upstream commit 283c5c4c34b4c8d1ebd038d8f360c5ba7fcc767b ]
A couple of runs of different AI tools have generated something like the following bug report:
In nested_domain_free(), when refcount_dec_and_test() returns false (other nested domains still reference the same gdom_info), the function returns without calling kfree(ndom), leaking the nested_domain structure. This problem wasn't introduced by this patch, but exists in the code from commit 757d2b1fdf5b that the patch modifies. Each nested_domain (ndom) is allocated individually in amd_iommu_alloc_domain_nested() via kzalloc_obj(*ndom). The .free callback is the sole point responsible for freeing this domain. When the refcount is > 0, only the xa_unlock_irqrestore is performed and the function returns, leaving ndom permanently allocated. This leak occurs every time a nested domain sharing a gDomID is destroyed while other domains still use that gDomID.
There is a similar leak later in this function in the WARN_ON() test when the mapping is already NULL. Switch to a RAII-based cleanup for ndom, since it should always be freed in this function.
--- drivers/iommu/amd/nested.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/iommu/amd/nested.c +1 -2
@@ -263,7 +263,7 @@ static void nested_domain_free(struct iommu_domain *dom) {unsigned long irqflags;struct guest_domain_mapping_info *curr; -struct nested_domain *ndom =to_ndomain (dom); + struct nested_domain *ndom __free(kfree) = to_ndomain(dom);struct amd_iommu_viommu *aviommu = ndom->viommu;xa_lock_irqsave (&aviommu->gdomid_array, irqflags);
@@ -290,7 +290,6 @@ static void nested_domain_free(struct iommu_domain *dom)amd_iommu_pdom_id_free (ndom->gdom_info->hdom_id);kfree (curr); -kfree (ndom); }static const struct iommu_domain_ops nested_domain_ops = {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 200/744 ALSA: hda: cs35l41: validate and free ACPI mute object
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guangshuo Li <[email protected]>
[ Upstream commit 3b597d24dc0455ae926f1053f97c2725038fc3cd ]
cs35l41_get_acpi_mute_state() evaluates a _DSM method to get the ACPI mute state and reads the first byte from the returned object.
However, the returned ACPI object is owned by the caller and is never freed after use, so each successful query leaks the _DSM result object.
The code also assumes that the returned object is a buffer with at least one byte. A malformed firmware response can return a different object type or an empty buffer, and the direct ret->buffer.pointer dereference can then access an invalid pointer.
Use the typed _DSM helper, validate that the returned buffer contains at least one byte, and free the ACPI object after reading it.
--- sound/hda/codecs/side-codecs/cs35l41_hda.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)
sound/hda/codecs/side-codecs/cs35l41_hda.c +10 -1
@@ -1434,10 +1434,19 @@ static int cs35l41_get_acpi_mute_state(struct cs35l41_hda *cs35l41, acpi_handleguid_parse (CS35L41_UUID , &guid);if (cs35l41_dsm_supported (handle,CS35L41_DSM_GET_MUTE )) { - ret =acpi_evaluate_dsm (handle, &guid,0 ,CS35L41_DSM_GET_MUTE ,NULL ); + ret =acpi_evaluate_dsm_typed (handle, &guid,0 , +CS35L41_DSM_GET_MUTE ,NULL , +ACPI_TYPE_BUFFER ); +if (!ret)return -EINVAL ; +if (!ret->buffer.length || !ret->buffer.pointer) { +ACPI_FREE (ret); +return -EINVAL ; + } + mute = *ret->buffer.pointer; +ACPI_FREE (ret);dev_dbg (cs35l41->dev,"CS35L41_DSM_GET_MUTE: %d\n" , mute); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 201/744 ASoC: bt-sco: fix duplicate DAPM widget names for wideband DAI
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shengjiu Wang <[email protected]>
[ Upstream commit 0b604e886ece11b71c4daaeccc512c784b89b014 ]
The bt-sco-pcm-wb DAI uses the same stream_name strings as bt-sco-pcm ("Playback" and "Capture"). This causes duplicate DAPM AIF widget names within the same component, leading to debugfs warnings:
debugfs: 'Playback' already exists in 'dapm'
debugfs: 'Capture' already exists in 'dapm'
Give the wideband DAI distinct stream names ("WB Playback" and "WB Capture") and add corresponding DAPM AIF widgets and routes for them.
--- sound/soc/codecs/bt-sco.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
sound/soc/codecs/bt-sco.c +8 -2
@@ -17,11 +17,17 @@ static const struct snd_soc_dapm_widget bt_sco_widgets[] = { SND_SOC_NOPM, 0, 0),SND_SOC_DAPM_AIF_OUT ("BT_SCO_TX" ,"Capture" ,0 ,SND_SOC_NOPM ,0 ,0 ), +SND_SOC_DAPM_AIF_IN ("BT_SCO_RX_WB" ,"WB Playback" ,0 , +SND_SOC_NOPM ,0 ,0 ), +SND_SOC_DAPM_AIF_OUT ("BT_SCO_TX_WB" ,"WB Capture" ,0 , + SND_SOC_NOPM, 0, 0), };static const struct snd_soc_dapm_route bt_sco_routes[] = { {"BT_SCO_TX" ,NULL ,"RX" }, {"TX" ,NULL ,"BT_SCO_RX" }, + {"BT_SCO_TX_WB" ,NULL ,"RX" }, + {"TX" ,NULL ,"BT_SCO_RX_WB" }, }; static struct snd_soc_dai_driver bt_sco_dai[] = {
@@ -45,14 +51,14 @@ static struct snd_soc_dai_driver bt_sco_dai[] = { { .name = "bt-sco-pcm-wb", .playback = { - .stream_name = "Playback", + .stream_name = "WB Playback", .channels_min = 1, .channels_max = 1, .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000, .formats = SNDRV_PCM_FMTBIT_S16_LE, }, .capture = { - .stream_name = "Capture", + .stream_name = "WB Capture", .channels_min = 1, .channels_max = 1, .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 202/744 arm_mpam: Fix software reset values of MPAMCFG_PRI
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ben Horgan <[email protected]>
[ Upstream commit 9469764292e0d6825c9bf51d75682e3a623b9b6b ]
Priority partitioning is not supported other than to set the per-PARTID defaults in MPAMCFG_PRI, INTPRI and DSPRI, to the highest priority. When 0 is the lowest priority, all ones is the highest priority. However, these values are calculated with an extra higher bit set.
Luckily, there is still no chance of setting functional bits incorrectly. When the priority widths are maximal, this is ensured as the fields have width 16 and a u16 holds the value for each field. When the widths are smaller, the higher order bits beyond the advertised widths, MPAMF_PRI_IDR.DSPRI_WD and MPAMF_PRI_IDR.INTPRI_WD, in the priority fields INTPRI and DSPRI are not used to calculate the priority. It is not specified whether these higher order bits are RAZ/WI or Res0 and so it is desirable not to set them to avoid the chance of misleading reads.
Correct the priority reset values.
--- drivers/resctrl/mpam_devices.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-)
drivers/resctrl/mpam_devices.c +16 -10
@@ -1535,12 +1535,9 @@ static u16 mpam_wa_t241_calc_min_from_max(struct mpam_props *props,static void mpam_reprogram_ris_partid (struct mpam_msc_ris *ris,u16 partid,struct mpam_config *cfg) { -u32 pri_val =0 ;u16 cmax =MPAMCFG_CMAX_CMAX ;struct mpam_msc *msc = ris->vmsc->msc;struct mpam_props *rprops = &ris->props; -u16 dspri =GENMASK (rprops->dspri_wd,0 ); -u16 intpri =GENMASK (rprops->intpri_wd,0 );mutex_lock (&msc->part_sel_lock);__mpam_part_sel (ris->ris_idx, partid, msc);
@@ -1605,16 +1602,25 @@ static void mpam_reprogram_ris_partid(struct mpam_msc_ris *ris, u16 partid,if (mpam_has_feature (mpam_feat_intpri_part, rprops) ||mpam_has_feature (mpam_feat_dspri_part, rprops)) { -/* aces high? */ -if (!mpam_has_feature (mpam_feat_intpri_part_0_low, rprops)) - intpri =0 ; -if (!mpam_has_feature (mpam_feat_dspri_part_0_low, rprops)) - dspri =0 ; +u32 pri_val =0 ; + +if (mpam_has_feature (mpam_feat_intpri_part, rprops)) { +u16 intpri =GENMASK (rprops->intpri_wd -1 ,0 ); + +/* aces high? */ +if (!mpam_has_feature (mpam_feat_intpri_part_0_low, rprops)) + intpri =0 ; -if (mpam_has_feature (mpam_feat_intpri_part, rprops)) pri_val |=FIELD_PREP (MPAMCFG_PRI_INTPRI , intpri); -if (mpam_has_feature (mpam_feat_dspri_part, rprops)) + } +if (mpam_has_feature (mpam_feat_dspri_part, rprops)) { +u16 dspri =GENMASK (rprops->dspri_wd -1 ,0 ); + +if (!mpam_has_feature (mpam_feat_dspri_part_0_low, rprops)) + dspri =0 ; + pri_val |=FIELD_PREP (MPAMCFG_PRI_DSPRI , dspri); + }mpam_write_partsel_reg (msc,PRI , pri_val); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 203/744 arm_mpam: Fix MPAMCFG_MBW_PBM register setting
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Fenghua Yu <[email protected]>
[ Upstream commit 021118ce5ea954ec316d7e30bcf4506e12eb5222 ]
MPAMCFG_MBW_PBM is written from cfg if cfg has the MBW partition feature. It is reset when cfg does not have the MBW partition feature.
But the register handling is reversed. This may cause an incorrect register setting. For example, during an MPAM reset, reset_cfg is empty (no MBW partition feature set), and cfg->mbw_pbm is 0. Instead of resetting MPAMCFG_MBW_PBM to all 1's, the current logic will set it to cfg->mbw_pbm, which is 0.
Fix the issue by swapping the if/else branches.
--- drivers/resctrl/mpam_devices.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/resctrl/mpam_devices.c +2 -2
@@ -1563,9 +1563,9 @@ static void mpam_reprogram_ris_partid(struct mpam_msc_ris *ris, u16 partid,if (mpam_has_feature (mpam_feat_mbw_part, rprops)) {if (mpam_has_feature (mpam_feat_mbw_part, cfg)) -mpam_reset_msc_bitmap (msc,MPAMCFG_MBW_PBM , rprops->mbw_pbm_bits); -else mpam_write_partsel_reg (msc,MBW_PBM , cfg->mbw_pbm); +else +mpam_reset_msc_bitmap (msc,MPAMCFG_MBW_PBM , rprops->mbw_pbm_bits); }if (mpam_has_feature (mpam_feat_mbw_min, rprops)) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 204/744 arm_mpam: guard MBWU state before adding it to garbage
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guangshuo Li <[email protected]>
[ Upstream commit 977f52909c624210178a1247fab0b02b110c1106 ]
__destroy_component_cfg() adds each RIS mbwu_state object to the MPAM garbage list when destroying component configuration.
However, mbwu_state is allocated per RIS and only for RISes with MBWU monitors. A component can therefore have comp->cfg allocated while some RISes still have ris->mbwu_state set to NULL.
Passing a NULL mbwu_state to add_to_garbage() dereferences the NULL pointer inside the macro.
Skip RISes that do not have an mbwu_state object before adding them to the garbage list.
--- drivers/resctrl/mpam_devices.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/resctrl/mpam_devices.c +4 -2
@@ -2595,8 +2595,10 @@ static void __destroy_component_cfg(struct mpam_component *comp) msc = vmsc->msc;if (mpam_mon_sel_lock (msc)) { -list_for_each_entry (ris, &vmsc->ris, vmsc_list) -add_to_garbage (ris->mbwu_state); +list_for_each_entry (ris, &vmsc->ris, vmsc_list) { +if (ris->mbwu_state) +add_to_garbage (ris->mbwu_state); + }mpam_mon_sel_unlock (msc); } }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 205/744 ASoC: cs35l56: Fix potential probe() deadlock
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Richard Fitzgerald <[email protected]>
[ Upstream commit 93c2a8ea2454b7b14eb378a58cad8a83c0ffc903 ]
On I2C/SPI call cs35l56_init() before calling snd_soc_register_component() to prevent the potential for a deadlock on init_completion.
For most buses all the hardware would be ready when probe() returns, but on SoundWire, probe() must return before the SoundWire bus driver will enumerate the device. All access to the registers must be deferred until the driver receives an ATTACHED notification. But anything that could return -EPROBE_DEFER must be called during probe, and that includes snd_soc_register_component(). Because of that, on SoundWire the ASoC component can be created before the registers are accssible, so cs35l56_component_probe() waits for init_completion to signal that the registers are accessible.
On I2C/SPI this 2-stage startup isn't required so their probe() functions simply called cs35l56_common_probe() and then cs35l56_init(). The problem with this was that snd_soc_register_component() was still called early. If this triggered ASoC to create the card, ASoC would call cs35l56_component_probe() which waits on init_completion - but this would be running inside the cs35l56 driver probe() so blocking it from reaching the code that signals init_completion, causing a deadlock.
--- sound/soc/codecs/cs35l56-i2c.c | 4 +--- sound/soc/codecs/cs35l56-spi.c | 4 +--- sound/soc/codecs/cs35l56.c | 15 +++++++++++++++ 3 files changed, 17 insertions(+), 6 deletions(-)
sound/soc/codecs/cs35l56-i2c.c +1 -3
@@ -55,9 +55,7 @@ static int cs35l56_i2c_probe(struct i2c_client *client)if (ret !=0 )return ret; - ret =cs35l56_init (cs35l56); -if (ret ==0 ) - ret =cs35l56_irq_request (&cs35l56->base, client->irq); + ret =cs35l56_irq_request (&cs35l56->base, client->irq);if (ret <0 )cs35l56_remove (cs35l56);
sound/soc/codecs/cs35l56-spi.c +1 -3
@@ -44,9 +44,7 @@ static int cs35l56_spi_probe(struct spi_device *spi)if (ret !=0 )return ret; - ret =cs35l56_init (cs35l56); -if (ret ==0 ) - ret =cs35l56_irq_request (&cs35l56->base, spi->irq); + ret =cs35l56_irq_request (&cs35l56->base, spi->irq);if (ret <0 )cs35l56_remove (cs35l56);
sound/soc/codecs/cs35l56.c +15 -0
@@ -1975,6 +1975,16 @@ int cs35l56_common_probe(struct cs35l56_private *cs35l56) goto err; } +/* +* On SoundWire the cs35l56_init() cannot be run until after the +* device has been enumerated by the SoundWire core. +*/ +if (!cs35l56->sdw_peripheral) { + ret =cs35l56_init (cs35l56); +if (ret) + goto err_remove_wm_adsp; + } + ret =snd_soc_register_component (cs35l56->base.dev, &soc_component_dev_cs35l56, cs35l56_dai,ARRAY_SIZE (cs35l56_dai));
@@ -1989,6 +1999,11 @@ int cs35l56_common_probe(struct cs35l56_private *cs35l56)wm_adsp2_remove (&cs35l56->dsp); err: +if (pm_runtime_enabled (cs35l56->base.dev)) { +pm_runtime_dont_use_autosuspend (cs35l56->base.dev); +pm_runtime_disable (cs35l56->base.dev); + } +gpiod_set_value_cansleep (cs35l56->base.reset_gpio,0 );regulator_bulk_disable (ARRAY_SIZE (cs35l56->supplies), cs35l56->supplies);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 206/744 ASoC: cs35l56: Use complete_all() to signal init_completion
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Richard Fitzgerald <[email protected]>
[ Upstream commit e0bffb63a2eda0af82ed7e6357ac67c2db990c21 ]
In cs35l56_init() use complete_all() to signal init_completion instead of complete().
cs35l56_init() was signaling init_completion using the complete() function. This only releases ONE waiter.
If cs35l56_component_probe() was called multiple times the first time would consume that one signal, then future calls would timeout waiting for the completion. This could happen if:
- The component is probed, removed, then probed again without the cs35l56 module being removed.
- A call to component_probe() returns an error and ASoC calls it again later.
It should use complete_all() so that after it has been signaled it will allow any code that waits on it to continue immediately.
The one case where the driver must wait for initialization to run again is when waiting for a reboot after firmware download, and here the code correctly calls reinit_completion() first.
--- sound/soc/codecs/cs35l56.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
sound/soc/codecs/cs35l56.c +1 -1
@@ -2089,7 +2089,7 @@ int cs35l56_init(struct cs35l56_private *cs35l56)return dev_err_probe (cs35l56->base.dev, ret,"Failed to write ASP1_CONTROL3\n" ); cs35l56->base.init_done = true; -complete (&cs35l56->init_completion); +complete_all (&cs35l56->init_completion);return 0 ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 207/744 wifi: iwlwifi: mvm: validate SAR GEO response payload size
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pagadala Yesu Anjaneyulu <[email protected]>
[ Upstream commit 408d7da38272ce48e2db79b8a9895999f94d7655 ]
The SAR GEO command response is cast to iwl_geo_tx_power_profiles_resp without verifying the payload length. A malformed or unexpected firmware response can lead to reading an invalid structure layout.
Add an explicit size check before accessing the response data and return -EIO when the payload size is wrong.
--- drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
drivers/net/wireless/intel/iwlwifi/mvm/fw.c +10 -0
@@ -964,12 +964,22 @@ int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm)return ret; } +if (IWL_FW_CHECK (mvm, +iwl_rx_packet_payload_len (cmd.resp_pkt) != +sizeof (*resp), +"Wrong size for iwl_geo_tx_power_profiles_resp: %d\n" , +iwl_rx_packet_payload_len (cmd.resp_pkt))) { + ret = -EIO ; + goto out; + } + resp = (void *)cmd.resp_pkt->data; ret =le32_to_cpu (resp->profile_idx);if (WARN_ON (ret >BIOS_GEO_MAX_PROFILE_NUM )) ret = -EIO ; +out:iwl_free_resp (&cmd);return ret; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 208/744 wifi: iwlwifi: fix pointer arithmetic in iwl_add_mcc_to_tas_block_list
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Emmanuel Grumbach <[email protected]>
[ Upstream commit bc796f84ec9a95b356959ec7caf1d4fce33f3a76 ]
The expression list[*size++] increments the pointer 'size' rather than the u8 value it points to (operator precedence: ++ binds to the pointer before the dereference). As a result the block-list entry is written at the correct index but *size is never incremented, so the caller's count stays at zero and subsequent calls overwrite slot 0 every time.
Change to list[(*size)++] so that the value pointed to by size is incremented after use as the array index.
--- drivers/net/wireless/intel/iwlwifi/fw/regulatory.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/wireless/intel/iwlwifi/fw/regulatory.c +1 -1
@@ -384,7 +384,7 @@ bool iwl_add_mcc_to_tas_block_list(u16 *list, u8 *size, u16 mcc)if (*size >=IWL_WTAS_BLACK_LIST_MAX )return false; - list[*size++] = mcc; + list[(*size)++] = mcc;return true; }IWL_EXPORT_SYMBOL (iwl_add_mcc_to_tas_block_list);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 209/744 wifi: iwlwifi: validate payload length in iwl_pnvm_complete_fn
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Emmanuel Grumbach <[email protected]>
[ Upstream commit daec24a5ed5da77a108e246ad77aa8b889911f93 ]
iwl_pnvm_complete_fn() casts pkt->data directly to struct iwl_pnvm_init_complete_ntfy and reads the status field without first verifying that the firmware notification payload is large enough to contain that structure.
Add a WARN_ON_ONCE check against sizeof(*pnvm_ntf) and return early without reading uninitialised memory if the payload is too short.
--- drivers/net/wireless/intel/iwlwifi/fw/pnvm.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
drivers/net/wireless/intel/iwlwifi/fw/pnvm.c +8 -1
@@ -1,6 +1,6 @@// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* -* Copyright(c) 2020-2025 Intel Corporation +* Copyright(c) 2020-2026 Intel Corporation */ #include "iwl-drv.h"
@@ -12,6 +12,7 @@#include "fw/api/alive.h" #include "fw/uefi.h" #include "fw/img.h" +#include "fw/dbg.h" #define IWL_PNVM_REDUCED_CAP_BIT BIT(25)
@@ -26,6 +27,12 @@ static bool iwl_pnvm_complete_fn(struct iwl_notif_wait_data *notif_wait,struct iwl_trans *trans = (struct iwl_trans *)data;struct iwl_pnvm_init_complete_ntfy *pnvm_ntf = (void *)pkt->data; +if (IWL_FW_CHECK (trans, +iwl_rx_packet_payload_len (pkt) <sizeof (*pnvm_ntf), +"Bad notif len: %d\n" , +iwl_rx_packet_payload_len (pkt))) +return true; +IWL_DEBUG_FW (trans,"PNVM complete notification received with status 0x%0x\n" ,le32_to_cpu (pnvm_ntf->status));
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 210/744 wifi: iwlwifi: mvm: fix read in wake packet notification handler
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shahar Tzarfati <[email protected]>
[ Upstream commit 9d7657aae8c1579584c67b0b66114a6a98db8b2f ]
In iwl_mvm_wowlan_store_wake_pkt(), packet_len was initialized from notif->wake_packet_length before the explicit check that len >= sizeof(*notif).
Move the assignment of packet_len to after the size check so that notif->wake_packet_length is only accessed once the payload length has been validated.
--- drivers/net/wireless/intel/iwlwifi/mvm/d3.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/net/wireless/intel/iwlwifi/mvm/d3.c +2 -1
@@ -2756,7 +2756,7 @@ static int iwl_mvm_wowlan_store_wake_pkt(struct iwl_mvm *mvm, struct iwl_wowlan_status_data *status, u32 len) { -u32 data_size, packet_len =le32_to_cpu (notif->wake_packet_length); +u32 data_size, packet_len;if (len <sizeof (*notif)) {IWL_ERR (mvm,"Invalid WoWLAN wake packet notification!\n" );
@@ -2775,6 +2775,7 @@ static int iwl_mvm_wowlan_store_wake_pkt(struct iwl_mvm *mvm,return -EIO ; } + packet_len =le32_to_cpu (notif->wake_packet_length); data_size = len - offsetof(struct iwl_wowlan_wake_pkt_notif , wake_packet);/* data_size got the padding from the notification, remove it. */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 211/744 usb: atm: ueagle-atm: reject descriptors that confuse probe and disconnect
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Diego Fernando Mancera Gomez <[email protected]>
[ Upstream commit 71132cedd1ecbc4032d76e9928c18a10f7e39b80 ]
uea_probe() distinguishes a pre-firmware device from a post-firmware one using the USB id (UEA_IS_PREFIRM()), and stores a different object as the interface data in each case: a 'struct completion' for a pre-firmware device (to be waited on in .disconnect()), or a 'struct usbatm_data' for a post-firmware one.
uea_disconnect() instead tells the two apart by the number of interfaces of the active configuration (a pre-firmware device exposes a single interface, ADI930 has 2 and eagle has 3), and casts the interface data accordingly.
Because the two handlers use different criteria, a crafted device that advertises a pre-firmware id together with a multi-interface descriptor (or a post-firmware id with a single interface) makes them disagree: the small 'struct completion' stored by uea_probe() is then passed to usbatm_usb_disconnect(), which casts it to 'struct usbatm_data' and takes instance->serialize, reading past the end of the allocation:
BUG: KASAN: slab-out-of-bounds in __mutex_lock+0x152a/0x1b80 Read of size 8 at addr ffff8880470e2c60 by task kworker/1:2/982 ... __mutex_lock+0x152a/0x1b80 usbatm_usb_disconnect+0x70/0x820 uea_disconnect+0x133/0x2c0 usb_unbind_interface+0x1dd/0x9e0 ... which belongs to the cache kmalloc-96 of size 96 The buggy address is located 0 bytes to the right of allocated 96-byte region [ffff8880470e2c00, ffff8880470e2c60)
Reject such inconsistent descriptors in uea_probe() so that both handlers always make the same pre/post-firmware decision.
--- drivers/usb/atm/ueagle-atm.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+)
drivers/usb/atm/ueagle-atm.c +17 -0
@@ -2551,6 +2551,7 @@ static struct usbatm_driver uea_usbatm_driver = {static int uea_probe (struct usb_interface *intf,const struct usb_device_id *id) {struct usb_device *usb =interface_to_usbdev (intf); +bool single_iface = usb->config->desc.bNumInterfaces ==1 ;int ret; uea_dbg(usb, "ADSL device found with vid (%#X) pid (%#X) Rev (%#X): %s\n",
@@ -2559,6 +2560,22 @@ static int uea_probe(struct usb_interface *intf, const struct usb_device_id *id)le16_to_cpu (usb->descriptor.bcdDevice), chip_name[UEA_CHIP_VERSION(id)]); +/* +* uea_probe() decides between the pre-firmware and post-firmware case +* from the USB id and stores a different object as interface data in +* each case: a struct completion for a pre-firmware device, a struct +* usbatm_data for a post-firmware one. uea_disconnect() instead tells +* the two apart by the number of interfaces (a pre-firmware device +* exposes a single interface, ADI930 has 2 and eagle has 3). A crafted +* device advertising a pre-firmware id together with a multi-interface +* descriptor (or the other way around) makes the two disagree, so that +* usbatm_usb_disconnect() treats the small completion object as a +* struct usbatm_data and reads out of bounds. Reject such inconsistent +* descriptors so both paths make the same decision. +*/ +if (UEA_IS_PREFIRM (id) != single_iface) +return -ENODEV ; +usb_reset_device (usb);if (UEA_IS_PREFIRM (id)) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 212/744 drivers/virt: pkvm: Fix end calculation in mmio_guard_ioremap_hook()
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mostafa Saleh <[email protected]>
[ Upstream commit 62c740f823a8e47ffe56e45a7472c27cf988e2f6 ]
Sashiko (locally) reports a logical issues in mmio_guard_ioremap_hook()
mmio_guard_ioremap_hook() attempts to handle unaligned addresses and sizes. However, aligning the start address before adding the size, might shift the end to the page before.
--- drivers/virt/coco/pkvm-guest/arm-pkvm-guest.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/virt/coco/pkvm-guest/arm-pkvm-guest.c +1 -1
@@ -82,8 +82,8 @@ static int mmio_guard_ioremap_hook(phys_addr_t phys, size_t size,if (protval != PROT_DEVICE_nGnRE && protval != PROT_DEVICE_nGnRnE)return 0 ; + end =PAGE_ALIGN (phys + size); phys =PAGE_ALIGN_DOWN (phys); - end = phys +PAGE_ALIGN (size);while (phys < end) {const int func_id =ARM_SMCCC_VENDOR_HYP_KVM_MMIO_GUARD_FUNC_ID ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 213/744 hwmon: Drop unused i2c driver_data
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Uwe Kleine-König (The Capable Hub) <[email protected]>
[ Upstream commit b3de407ae66ffef6290a31363205e9751db0537a ]
The four drivers all don't make use of the value that was explicitly assigned to the .driver_data member. Drop the assignment.
While touching these lines also make the assignments use named initializers and drop a comma after the end-of-list marker.
Stable-dep-of: af01dab0c39a ("hwmon: (pmbus/max34440) block unsupported VIN and IIN limit registers")
--- drivers/hwmon/lm80.c | 4 ++-- drivers/hwmon/pmbus/aps-379.c | 4 ++-- drivers/hwmon/pmbus/lt3074.c | 4 ++-- drivers/hwmon/tsc1641.c | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-)
drivers/hwmon/lm80.c +2 -2
@@ -622,8 +622,8 @@ static int lm80_probe(struct i2c_client *client)*/ static const struct i2c_device_id lm80_id[] = { - {"lm80" ,0 }, - {"lm96080" ,1 }, + {"lm80" }, + {"lm96080" }, { } };MODULE_DEVICE_TABLE (i2c, lm80_id);
drivers/hwmon/pmbus/aps-379.c +2 -2
@@ -100,8 +100,8 @@ static struct pmbus_driver_info aps_379_info = { };static const struct i2c_device_id aps_379_id[] = { - {"aps-379" ,0 }, - {}, + { .name ="aps-379" }, + { } };MODULE_DEVICE_TABLE (i2c, aps_379_id);
drivers/hwmon/pmbus/lt3074.c +2 -2
@@ -95,8 +95,8 @@ static int lt3074_probe(struct i2c_client *client) }static const struct i2c_device_id lt3074_id[] = { - {"lt3074" ,0 }, - {} + { .name ="lt3074" }, + { } };MODULE_DEVICE_TABLE (i2c, lt3074_id);
drivers/hwmon/tsc1641.c +1 -1
@@ -721,7 +721,7 @@ static int tsc1641_probe(struct i2c_client *client) }static const struct i2c_device_id tsc1641_id[] = { - {"tsc1641" ,0 }, + { .name ="tsc1641" }, { } };MODULE_DEVICE_TABLE (i2c, tsc1641_id);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 214/744 hwmon: Use named initializers for arrays of i2c_device_data
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Uwe Kleine-König (The Capable Hub) <[email protected]>
[ Upstream commit 4a9e6a9230c88a71916301b9fe6627413ebc2574 ]
While being less compact, using named initializers allows to more easily see which members of the structs are assigned which value without having to lookup the declaration of the struct. And it's also more robust against changes to the struct definition.
The mentioned robustness is relevant for a planned change to struct i2c_device_id that replaces .driver_data by an anonymous union.
While touching all these arrays, unify indention and usage of commas.
This patch doesn't modify the compiled arrays, only their representation in source form benefits. The former was confirmed with x86 and arm64 builds.
Stable-dep-of: af01dab0c39a ("hwmon: (pmbus/max34440) block unsupported VIN and IIN limit registers")
--- drivers/hwmon/ad7414.c | 4 +- drivers/hwmon/ad7418.c | 6 +- drivers/hwmon/adc128d818.c | 2 +- drivers/hwmon/adm1025.c | 4 +- drivers/hwmon/adm1026.c | 2 +- drivers/hwmon/adm1029.c | 2 +- drivers/hwmon/adm1031.c | 4 +- drivers/hwmon/adm1177.c | 4 +- drivers/hwmon/adm9240.c | 6 +- drivers/hwmon/ads7828.c | 4 +- drivers/hwmon/adt7410.c | 8 +-- drivers/hwmon/adt7411.c | 2 +- drivers/hwmon/adt7462.c | 2 +- drivers/hwmon/adt7470.c | 2 +- drivers/hwmon/adt7475.c | 8 +-- drivers/hwmon/aht10.c | 8 +-- drivers/hwmon/amc6821.c | 2 +- drivers/hwmon/asb100.c | 2 +- drivers/hwmon/asc7621.c | 6 +- drivers/hwmon/atxp1.c | 2 +- drivers/hwmon/chipcap2.c | 16 ++--- drivers/hwmon/dme1737.c | 4 +- drivers/hwmon/ds1621.c | 10 +-- drivers/hwmon/ds620.c | 4 +- drivers/hwmon/emc1403.c | 24 +++---- drivers/hwmon/emc2103.c | 2 +- drivers/hwmon/emc2305.c | 8 +-- drivers/hwmon/emc6w201.c | 2 +- drivers/hwmon/f75375s.c | 6 +- drivers/hwmon/fschmd.c | 14 ++-- drivers/hwmon/ftsteutates.c | 2 +- drivers/hwmon/g760a.c | 2 +- drivers/hwmon/g762.c | 6 +- drivers/hwmon/gl518sm.c | 2 +- drivers/hwmon/gl520sm.c | 2 +- drivers/hwmon/hih6130.c | 2 +- drivers/hwmon/hs3001.c | 4 +- drivers/hwmon/htu31.c | 2 +- drivers/hwmon/ina209.c | 2 +- drivers/hwmon/ina238.c | 12 ++-- drivers/hwmon/ina2xx.c | 16 ++--- drivers/hwmon/ina3221.c | 2 +- drivers/hwmon/isl28022.c | 2 +- drivers/hwmon/jc42.c | 2 +- drivers/hwmon/lineage-pem.c | 4 +- drivers/hwmon/lm63.c | 6 +- drivers/hwmon/lm73.c | 2 +- drivers/hwmon/lm75.c | 62 ++++++++-------- drivers/hwmon/lm77.c | 2 +- drivers/hwmon/lm78.c | 4 +- drivers/hwmon/lm80.c | 4 +- drivers/hwmon/lm83.c | 4 +- drivers/hwmon/lm85.c | 24 +++---- drivers/hwmon/lm87.c | 4 +- drivers/hwmon/lm90.c | 96 ++++++++++++------------- drivers/hwmon/lm92.c | 6 +- drivers/hwmon/lm93.c | 4 +- drivers/hwmon/lm95234.c | 4 +- drivers/hwmon/lm95241.c | 4 +- drivers/hwmon/lm95245.c | 4 +- drivers/hwmon/ltc2945.c | 2 +- drivers/hwmon/ltc2947-i2c.c | 4 +- drivers/hwmon/ltc2990.c | 4 +- drivers/hwmon/ltc2991.c | 4 +- drivers/hwmon/ltc2992.c | 4 +- drivers/hwmon/ltc4151.c | 2 +- drivers/hwmon/ltc4215.c | 2 +- drivers/hwmon/ltc4222.c | 2 +- drivers/hwmon/ltc4245.c | 2 +- drivers/hwmon/ltc4260.c | 2 +- drivers/hwmon/ltc4261.c | 4 +- drivers/hwmon/max127.c | 2 +- drivers/hwmon/max16065.c | 12 ++-- drivers/hwmon/max1619.c | 2 +- drivers/hwmon/max1668.c | 6 +- drivers/hwmon/max31730.c | 2 +- drivers/hwmon/max31760.c | 2 +- drivers/hwmon/max31790.c | 2 +- drivers/hwmon/max31827.c | 6 +- drivers/hwmon/max6620.c | 2 +- drivers/hwmon/max6621.c | 2 +- drivers/hwmon/max6639.c | 2 +- drivers/hwmon/max6650.c | 4 +- drivers/hwmon/max6697.c | 20 +++--- drivers/hwmon/mc34vr500.c | 4 +- drivers/hwmon/mcp3021.c | 4 +- drivers/hwmon/nct6775-i2c.c | 26 +++---- drivers/hwmon/nct7802.c | 2 +- drivers/hwmon/nct7904.c | 4 +- drivers/hwmon/pcf8591.c | 2 +- drivers/hwmon/pmbus/acbel-fsg032.c | 4 +- drivers/hwmon/pmbus/adm1266.c | 2 +- drivers/hwmon/pmbus/adm1275.c | 20 +++--- drivers/hwmon/pmbus/bel-pfe.c | 6 +- drivers/hwmon/pmbus/bpa-rs600.c | 6 +- drivers/hwmon/pmbus/crps.c | 4 +- drivers/hwmon/pmbus/delta-ahe50dc-fan.c | 2 +- drivers/hwmon/pmbus/dps920ab.c | 4 +- drivers/hwmon/pmbus/fsp-3y.c | 4 +- drivers/hwmon/pmbus/hac300s.c | 4 +- drivers/hwmon/pmbus/ibm-cffps.c | 8 +-- drivers/hwmon/pmbus/ina233.c | 4 +- drivers/hwmon/pmbus/inspur-ipsps.c | 4 +- drivers/hwmon/pmbus/ir35221.c | 4 +- drivers/hwmon/pmbus/ir36021.c | 4 +- drivers/hwmon/pmbus/ir38064.c | 10 +-- drivers/hwmon/pmbus/irps5401.c | 4 +- drivers/hwmon/pmbus/isl68137.c | 96 ++++++++++++------------- drivers/hwmon/pmbus/lm25066.c | 10 +-- drivers/hwmon/pmbus/lt7182s.c | 4 +- drivers/hwmon/pmbus/ltc2978.c | 60 ++++++++-------- drivers/hwmon/pmbus/ltc3815.c | 2 +- drivers/hwmon/pmbus/max15301.c | 8 +-- drivers/hwmon/pmbus/max16064.c | 4 +- drivers/hwmon/pmbus/max16601.c | 10 +-- drivers/hwmon/pmbus/max17616.c | 2 +- drivers/hwmon/pmbus/max20730.c | 10 +-- drivers/hwmon/pmbus/max20751.c | 4 +- drivers/hwmon/pmbus/max31785.c | 8 +-- drivers/hwmon/pmbus/max34440.c | 18 ++--- drivers/hwmon/pmbus/max8688.c | 2 +- drivers/hwmon/pmbus/mp2856.c | 6 +- drivers/hwmon/pmbus/mp2888.c | 4 +- drivers/hwmon/pmbus/mp2891.c | 2 +- drivers/hwmon/pmbus/mp2925.c | 6 +- drivers/hwmon/pmbus/mp29502.c | 4 +- drivers/hwmon/pmbus/mp2975.c | 8 +-- drivers/hwmon/pmbus/mp2993.c | 2 +- drivers/hwmon/pmbus/mp5920.c | 2 +- drivers/hwmon/pmbus/mp5926.c | 4 +- drivers/hwmon/pmbus/mp5990.c | 4 +- drivers/hwmon/pmbus/mp9941.c | 2 +- drivers/hwmon/pmbus/mp9945.c | 4 +- drivers/hwmon/pmbus/mpq7932.c | 6 +- drivers/hwmon/pmbus/mpq8785.c | 10 +-- drivers/hwmon/pmbus/pim4328.c | 18 ++--- drivers/hwmon/pmbus/pli1209bc.c | 4 +- drivers/hwmon/pmbus/pm6764tr.c | 4 +- drivers/hwmon/pmbus/pmbus.c | 60 ++++++++-------- drivers/hwmon/pmbus/pxe1610.c | 8 +-- drivers/hwmon/pmbus/q54sj108a2.c | 8 +-- drivers/hwmon/pmbus/stef48h28.c | 4 +- drivers/hwmon/pmbus/stpddc60.c | 6 +- drivers/hwmon/pmbus/tda38640.c | 4 +- drivers/hwmon/pmbus/tps25990.c | 4 +- drivers/hwmon/pmbus/tps40422.c | 4 +- drivers/hwmon/pmbus/tps53679.c | 18 ++--- drivers/hwmon/pmbus/tps546d24.c | 4 +- drivers/hwmon/pmbus/ucd9000.c | 16 ++--- drivers/hwmon/pmbus/ucd9200.c | 18 ++--- drivers/hwmon/pmbus/xdp710.c | 2 +- drivers/hwmon/pmbus/xdp720.c | 4 +- drivers/hwmon/pmbus/xdpe12284.c | 8 +-- drivers/hwmon/pmbus/xdpe152c4.c | 6 +- drivers/hwmon/pmbus/xdpe1a2g7b.c | 6 +- drivers/hwmon/pmbus/zl6100.c | 44 ++++++------ drivers/hwmon/powr1220.c | 4 +- drivers/hwmon/pt5161l.c | 4 +- drivers/hwmon/sbtsi_temp.c | 4 +- drivers/hwmon/sg2042-mcu.c | 2 +- drivers/hwmon/sht21.c | 6 +- drivers/hwmon/sht3x.c | 8 +-- drivers/hwmon/sht4x.c | 4 +- drivers/hwmon/shtc1.c | 6 +- drivers/hwmon/smsc47m192.c | 2 +- drivers/hwmon/spd5118.c | 2 +- drivers/hwmon/stts751.c | 2 +- drivers/hwmon/tc654.c | 6 +- drivers/hwmon/tc74.c | 4 +- drivers/hwmon/thmc50.c | 4 +- drivers/hwmon/tmp102.c | 2 +- drivers/hwmon/tmp103.c | 2 +- drivers/hwmon/tmp108.c | 8 +-- drivers/hwmon/tmp401.c | 10 +-- drivers/hwmon/tmp421.c | 10 +-- drivers/hwmon/tmp464.c | 4 +- drivers/hwmon/tmp513.c | 4 +- drivers/hwmon/w83773g.c | 2 +- drivers/hwmon/w83781d.c | 8 +-- drivers/hwmon/w83791d.c | 2 +- drivers/hwmon/w83792d.c | 2 +- drivers/hwmon/w83793.c | 2 +- drivers/hwmon/w83795.c | 4 +- drivers/hwmon/w83l785ts.c | 2 +- drivers/hwmon/w83l786ng.c | 2 +- 185 files changed, 684 insertions(+), 684 deletions(-)
drivers/hwmon/ad7414.c +2 -2
@@ -205,8 +205,8 @@ static int ad7414_probe(struct i2c_client *client) }static const struct i2c_device_id ad7414_id[] = { - {"ad7414" }, - {} + { .name ="ad7414" }, + { } };MODULE_DEVICE_TABLE (i2c, ad7414_id);
drivers/hwmon/ad7418.c +3 -3
@@ -281,9 +281,9 @@ static int ad7418_probe(struct i2c_client *client) }static const struct i2c_device_id ad7418_id[] = { - {"ad7416" , ad7416 }, - {"ad7417" , ad7417 }, - {"ad7418" , ad7418 }, + { .name ="ad7416" , .driver_data = ad7416 }, + { .name ="ad7417" , .driver_data = ad7417 }, + { .name ="ad7418" , .driver_data = ad7418 }, { } };MODULE_DEVICE_TABLE (i2c, ad7418_id);
drivers/hwmon/adc128d818.c +1 -1
@@ -480,7 +480,7 @@ static int adc128_probe(struct i2c_client *client) }static const struct i2c_device_id adc128_id[] = { - {"adc128d818" }, + { .name ="adc128d818" }, { } };MODULE_DEVICE_TABLE (i2c, adc128_id);
drivers/hwmon/adm1025.c +2 -2
@@ -548,8 +548,8 @@ static int adm1025_probe(struct i2c_client *client) }static const struct i2c_device_id adm1025_id[] = { - {"adm1025" , adm1025 }, - {"ne1619" , ne1619 }, + { .name ="adm1025" , .driver_data = adm1025 }, + { .name ="ne1619" , .driver_data = ne1619 }, { } };MODULE_DEVICE_TABLE (i2c, adm1025_id);
drivers/hwmon/adm1026.c +1 -1
@@ -1857,7 +1857,7 @@ static int adm1026_probe(struct i2c_client *client) }static const struct i2c_device_id adm1026_id[] = { - {"adm1026" }, + { .name ="adm1026" }, { } };MODULE_DEVICE_TABLE (i2c, adm1026_id);
drivers/hwmon/adm1029.c +1 -1
@@ -382,7 +382,7 @@ static int adm1029_probe(struct i2c_client *client) }static const struct i2c_device_id adm1029_id[] = { - {"adm1029" }, + { .name ="adm1029" }, { } };MODULE_DEVICE_TABLE (i2c, adm1029_id);
drivers/hwmon/adm1031.c +2 -2
@@ -1055,8 +1055,8 @@ static int adm1031_probe(struct i2c_client *client) }static const struct i2c_device_id adm1031_id[] = { - {"adm1030" , adm1030 }, - {"adm1031" , adm1031 }, + { .name ="adm1030" , .driver_data = adm1030 }, + { .name ="adm1031" , .driver_data = adm1031 }, { } };MODULE_DEVICE_TABLE (i2c, adm1031_id);
drivers/hwmon/adm1177.c +2 -2
@@ -246,8 +246,8 @@ static int adm1177_probe(struct i2c_client *client) }static const struct i2c_device_id adm1177_id[] = { - {"adm1177" }, - {} + { .name ="adm1177" }, + { } };MODULE_DEVICE_TABLE (i2c, adm1177_id);
drivers/hwmon/adm9240.c +3 -3
@@ -794,9 +794,9 @@ static int adm9240_probe(struct i2c_client *client) }static const struct i2c_device_id adm9240_id[] = { - {"adm9240" , adm9240 }, - {"ds1780" , ds1780 }, - {"lm81" , lm81 }, + { .name ="adm9240" , .driver_data = adm9240 }, + { .name ="ds1780" , .driver_data = ds1780 }, + { .name ="lm81" , .driver_data = lm81 }, { } };MODULE_DEVICE_TABLE (i2c, adm9240_id);
drivers/hwmon/ads7828.c +2 -2
@@ -176,8 +176,8 @@ static int ads7828_probe(struct i2c_client *client) }static const struct i2c_device_id ads7828_device_ids[] = { - {"ads7828" , ads7828 }, - {"ads7830" , ads7830 }, + { .name ="ads7828" , .driver_data = ads7828 }, + { .name ="ads7830" , .driver_data = ads7830 }, { } };MODULE_DEVICE_TABLE (i2c, ads7828_device_ids);
drivers/hwmon/adt7410.c +4 -4
@@ -89,10 +89,10 @@ static int adt7410_i2c_probe(struct i2c_client *client) }static const struct i2c_device_id adt7410_ids[] = { - {"adt7410" }, - {"adt7420" }, - {"adt7422" }, - {} + { .name ="adt7410" }, + { .name ="adt7420" }, + { .name ="adt7422" }, + { } };MODULE_DEVICE_TABLE (i2c, adt7410_ids);
drivers/hwmon/adt7411.c +1 -1
@@ -670,7 +670,7 @@ static int adt7411_probe(struct i2c_client *client) }static const struct i2c_device_id adt7411_id[] = { - {"adt7411" }, + { .name ="adt7411" }, { } };MODULE_DEVICE_TABLE (i2c, adt7411_id);
drivers/hwmon/adt7462.c +1 -1
@@ -1809,7 +1809,7 @@ static int adt7462_probe(struct i2c_client *client) }static const struct i2c_device_id adt7462_id[] = { - {"adt7462" }, + { .name ="adt7462" }, { } };MODULE_DEVICE_TABLE (i2c, adt7462_id);
drivers/hwmon/adt7470.c +1 -1
@@ -1296,7 +1296,7 @@ static void adt7470_remove(struct i2c_client *client) }static const struct i2c_device_id adt7470_id[] = { - {"adt7470" }, + { .name ="adt7470" }, { } };MODULE_DEVICE_TABLE (i2c, adt7470_id);
drivers/hwmon/adt7475.c +4 -4
@@ -165,10 +165,10 @@ static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };enum chips { adt7473, adt7475, adt7476, adt7490 };static const struct i2c_device_id adt7475_id[] = { - {"adt7473" , adt7473 }, - {"adt7475" , adt7475 }, - {"adt7476" , adt7476 }, - {"adt7490" , adt7490 }, + { .name ="adt7473" , .driver_data = adt7473 }, + { .name ="adt7475" , .driver_data = adt7475 }, + { .name ="adt7476" , .driver_data = adt7476 }, + { .name ="adt7490" , .driver_data = adt7490 }, { } };MODULE_DEVICE_TABLE (i2c, adt7475_id);
drivers/hwmon/aht10.c +4 -4
@@ -55,10 +55,10 @@enum aht10_variant { aht10, aht20, dht20};static const struct i2c_device_id aht10_id[] = { - {"aht10" , aht10 }, - {"aht20" , aht20 }, - {"dht20" , dht20 }, - { }, + { .name ="aht10" , .driver_data = aht10 }, + { .name ="aht20" , .driver_data = aht20 }, + { .name ="dht20" , .driver_data = dht20 }, + { } };MODULE_DEVICE_TABLE (i2c, aht10_id);
drivers/hwmon/amc6821.c +1 -1
@@ -1083,7 +1083,7 @@ static int amc6821_probe(struct i2c_client *client) }static const struct i2c_device_id amc6821_id[] = { - {"amc6821" }, + { .name ="amc6821" }, { } };
drivers/hwmon/asb100.c +1 -1
@@ -213,7 +213,7 @@ static struct asb100_data *asb100_update_device(struct device *dev);static void asb100_init_client (struct i2c_client *client);static const struct i2c_device_id asb100_id[] = { - {"asb100" }, + { .name ="asb100" }, { } };MODULE_DEVICE_TABLE (i2c, asb100_id);
drivers/hwmon/asc7621.c +3 -3
@@ -1179,9 +1179,9 @@ static void asc7621_remove(struct i2c_client *client) }static const struct i2c_device_id asc7621_id[] = { - {"asc7621" , asc7621}, - {"asc7621a" , asc7621a}, - {}, + { .name ="asc7621" , .driver_data = asc7621 }, + { .name ="asc7621a" , .driver_data = asc7621a }, + { } };MODULE_DEVICE_TABLE (i2c, asc7621_id);
drivers/hwmon/atxp1.c +1 -1
@@ -278,7 +278,7 @@ static int atxp1_probe(struct i2c_client *client) };static const struct i2c_device_id atxp1_id[] = { - {"atxp1" }, + { .name ="atxp1" }, { } };MODULE_DEVICE_TABLE (i2c, atxp1_id);
drivers/hwmon/chipcap2.c +8 -8
@@ -736,14 +736,14 @@ static void cc2_remove(struct i2c_client *client) }static const struct i2c_device_id cc2_id[] = { - {"cc2d23" }, - {"cc2d23s" }, - {"cc2d25" }, - {"cc2d25s" }, - {"cc2d33" }, - {"cc2d33s" }, - {"cc2d35" }, - {"cc2d35s" }, + { .name ="cc2d23" }, + { .name ="cc2d23s" }, + { .name ="cc2d25" }, + { .name ="cc2d25s" }, + { .name ="cc2d33" }, + { .name ="cc2d33s" }, + { .name ="cc2d35" }, + { .name ="cc2d35s" }, { } };MODULE_DEVICE_TABLE (i2c, cc2_id);
drivers/hwmon/dme1737.c +2 -2
@@ -2515,8 +2515,8 @@ static void dme1737_i2c_remove(struct i2c_client *client) }static const struct i2c_device_id dme1737_id[] = { - {"dme1737" , dme1737 }, - {"sch5027" , sch5027 }, + { .name ="dme1737" , .driver_data = dme1737 }, + { .name ="sch5027" , .driver_data = sch5027 }, { } };MODULE_DEVICE_TABLE (i2c, dme1737_id);
drivers/hwmon/ds1621.c +5 -5
@@ -367,11 +367,11 @@ static int ds1621_probe(struct i2c_client *client) }static const struct i2c_device_id ds1621_id[] = { - {"ds1621" , ds1621 }, - {"ds1625" , ds1625 }, - {"ds1631" , ds1631 }, - {"ds1721" , ds1721 }, - {"ds1731" , ds1731 }, + { .name ="ds1621" , .driver_data = ds1621 }, + { .name ="ds1625" , .driver_data = ds1625 }, + { .name ="ds1631" , .driver_data = ds1631 }, + { .name ="ds1721" , .driver_data = ds1721 }, + { .name ="ds1731" , .driver_data = ds1731 }, { } };MODULE_DEVICE_TABLE (i2c, ds1621_id);
drivers/hwmon/ds620.c +2 -2
@@ -233,8 +233,8 @@ static int ds620_probe(struct i2c_client *client) }static const struct i2c_device_id ds620_id[] = { - {"ds620" }, - {} + { .name ="ds620" }, + { } };MODULE_DEVICE_TABLE (i2c, ds620_id);
drivers/hwmon/emc1403.c +12 -12
@@ -639,18 +639,18 @@ static const struct hwmon_chip_info emc1403_chip_info = {/* Last digit of chip name indicates number of channels */ static const struct i2c_device_id emc1403_idtable[] = { - {"emc1402" , emc1402 }, - {"emc1403" , emc1403 }, - {"emc1404" , emc1404 }, - {"emc1412" , emc1402 }, - {"emc1413" , emc1403 }, - {"emc1414" , emc1404 }, - {"emc1422" , emc1402 }, - {"emc1423" , emc1403 }, - {"emc1424" , emc1404 }, - {"emc1428" , emc1428 }, - {"emc1438" , emc1428 }, - {"emc1442" , emc1402 }, + { .name ="emc1402" , .driver_data = emc1402 }, + { .name ="emc1403" , .driver_data = emc1403 }, + { .name ="emc1404" , .driver_data = emc1404 }, + { .name ="emc1412" , .driver_data = emc1402 }, + { .name ="emc1413" , .driver_data = emc1403 }, + { .name ="emc1414" , .driver_data = emc1404 }, + { .name ="emc1422" , .driver_data = emc1402 }, + { .name ="emc1423" , .driver_data = emc1403 }, + { .name ="emc1424" , .driver_data = emc1404 }, + { .name ="emc1428" , .driver_data = emc1428 }, + { .name ="emc1438" , .driver_data = emc1428 }, + { .name ="emc1442" , .driver_data = emc1402 }, { } };MODULE_DEVICE_TABLE (i2c, emc1403_idtable);
drivers/hwmon/emc2103.c +1 -1
@@ -624,7 +624,7 @@ emc2103_probe(struct i2c_client *client) }static const struct i2c_device_id emc2103_ids[] = { - {"emc2103" }, + { .name ="emc2103" }, {/* LIST END */ } };MODULE_DEVICE_TABLE (i2c, emc2103_ids);
drivers/hwmon/emc2305.c +4 -4
@@ -59,10 +59,10 @@ enum emc230x_product_id { };static const struct i2c_device_id emc2305_ids[] = { - {"emc2305" }, - {"emc2303" }, - {"emc2302" }, - {"emc2301" }, + { .name ="emc2305" }, + { .name ="emc2303" }, + { .name ="emc2302" }, + { .name ="emc2301" }, { } };MODULE_DEVICE_TABLE (i2c, emc2305_ids);
drivers/hwmon/emc6w201.c +1 -1
@@ -464,7 +464,7 @@ static int emc6w201_probe(struct i2c_client *client) }static const struct i2c_device_id emc6w201_id[] = { - {"emc6w201" }, + { .name ="emc6w201" }, { } };MODULE_DEVICE_TABLE (i2c, emc6w201_id);
drivers/hwmon/f75375s.c +3 -3
@@ -877,9 +877,9 @@ static int f75375_detect(struct i2c_client *client, }static const struct i2c_device_id f75375_id[] = { - {"f75373" , f75373 }, - {"f75375" , f75375 }, - {"f75387" , f75387 }, + { .name ="f75373" , .driver_data = f75373 }, + { .name ="f75375" , .driver_data = f75375 }, + { .name ="f75387" , .driver_data = f75387 }, { } };MODULE_DEVICE_TABLE (i2c, f75375_id);
drivers/hwmon/fschmd.c +7 -7
@@ -225,13 +225,13 @@ static struct fschmd_data *fschmd_update_device(struct device *dev);*/ static const struct i2c_device_id fschmd_id[] = { - {"fscpos" , fscpos }, - {"fscher" , fscher }, - {"fscscy" , fscscy }, - {"fschrc" , fschrc }, - {"fschmd" , fschmd }, - {"fschds" , fschds }, - {"fscsyl" , fscsyl }, + { .name ="fscpos" , .driver_data = fscpos }, + { .name ="fscher" , .driver_data = fscher }, + { .name ="fscscy" , .driver_data = fscscy }, + { .name ="fschrc" , .driver_data = fschrc }, + { .name ="fschmd" , .driver_data = fschmd }, + { .name ="fschds" , .driver_data = fschds }, + { .name ="fscsyl" , .driver_data = fscsyl }, { } };MODULE_DEVICE_TABLE (i2c, fschmd_id);
drivers/hwmon/ftsteutates.c +1 -1
@@ -49,7 +49,7 @@static const unsigned short normal_i2c[] = {0x73 ,I2C_CLIENT_END };static const struct i2c_device_id fts_id[] = { - {"ftsteutates" }, + { .name ="ftsteutates" }, { } };MODULE_DEVICE_TABLE (i2c, fts_id);
drivers/hwmon/g760a.c +1 -1
@@ -197,7 +197,7 @@ static int g760a_probe(struct i2c_client *client) }static const struct i2c_device_id g760a_id[] = { - {"g760a" }, + { .name ="g760a" }, { } };MODULE_DEVICE_TABLE (i2c, g760a_id);
drivers/hwmon/g762.c +3 -3
@@ -44,9 +44,9 @@#define DRVNAME "g762"static const struct i2c_device_id g762_id[] = { - {"g761" }, - {"g762" }, - {"g763" }, + { .name ="g761" }, + { .name ="g762" }, + { .name ="g763" }, { } };MODULE_DEVICE_TABLE (i2c, g762_id);
drivers/hwmon/gl518sm.c +1 -1
@@ -642,7 +642,7 @@ static int gl518_probe(struct i2c_client *client) }static const struct i2c_device_id gl518_id[] = { - {"gl518sm" }, + { .name ="gl518sm" }, { } };MODULE_DEVICE_TABLE (i2c, gl518_id);
drivers/hwmon/gl520sm.c +1 -1
@@ -885,7 +885,7 @@ static int gl520_probe(struct i2c_client *client) }static const struct i2c_device_id gl520_id[] = { - {"gl520sm" }, + { .name ="gl520sm" }, { } };MODULE_DEVICE_TABLE (i2c, gl520_id);
drivers/hwmon/hih6130.c +1 -1
@@ -233,7 +233,7 @@ static int hih6130_probe(struct i2c_client *client)/* Device ID table */ static const struct i2c_device_id hih6130_id[] = { - {"hih6130" }, + { .name ="hih6130" }, { } };MODULE_DEVICE_TABLE (i2c, hih6130_id);
drivers/hwmon/hs3001.c +2 -2
@@ -169,8 +169,8 @@ static const struct hwmon_chip_info hs3001_chip_info = {/* device ID table */ static const struct i2c_device_id hs3001_ids[] = { - {"hs3001" }, - { }, + { .name ="hs3001" }, + { } };MODULE_DEVICE_TABLE (i2c, hs3001_ids);
drivers/hwmon/htu31.c +1 -1
@@ -322,7 +322,7 @@ static int htu31_probe(struct i2c_client *client) }static const struct i2c_device_id htu31_id[] = { - {"htu31" }, + { .name ="htu31" }, { } };MODULE_DEVICE_TABLE (i2c, htu31_id);
drivers/hwmon/ina209.c +1 -1
@@ -569,7 +569,7 @@ static void ina209_remove(struct i2c_client *client) }static const struct i2c_device_id ina209_id[] = { - {"ina209" }, + { .name ="ina209" }, { } };MODULE_DEVICE_TABLE (i2c, ina209_id);
drivers/hwmon/ina238.c +6 -6
@@ -837,12 +837,12 @@ static int ina238_probe(struct i2c_client *client) }static const struct i2c_device_id ina238_id[] = { - {"ina228" , ina228 }, - {"ina237" , ina237 }, - {"ina238" , ina238 }, - {"ina700" , ina700 }, - {"ina780" , ina780 }, - {"sq52206" , sq52206 }, + { .name ="ina228" , .driver_data = ina228 }, + { .name ="ina237" , .driver_data = ina237 }, + { .name ="ina238" , .driver_data = ina238 }, + { .name ="ina700" , .driver_data = ina700 }, + { .name ="ina780" , .driver_data = ina780 }, + { .name ="sq52206" , .driver_data = sq52206 }, { } };MODULE_DEVICE_TABLE (i2c, ina238_id);
drivers/hwmon/ina2xx.c +8 -8
@@ -1000,14 +1000,14 @@ static int ina2xx_probe(struct i2c_client *client) }static const struct i2c_device_id ina2xx_id[] = { - {"ina219" , ina219 }, - {"ina220" , ina219 }, - {"ina226" , ina226 }, - {"ina230" , ina226 }, - {"ina231" , ina226 }, - {"ina234" , ina234 }, - {"ina260" , ina260 }, - {"sy24655" , sy24655 }, + { .name ="ina219" , .driver_data = ina219 }, + { .name ="ina220" , .driver_data = ina219 }, + { .name ="ina226" , .driver_data = ina226 }, + { .name ="ina230" , .driver_data = ina226 }, + { .name ="ina231" , .driver_data = ina226 }, + { .name ="ina234" , .driver_data = ina234 }, + { .name ="ina260" , .driver_data = ina260 }, + { .name ="sy24655" , .driver_data = sy24655 }, { } };MODULE_DEVICE_TABLE (i2c, ina2xx_id);
drivers/hwmon/ina3221.c +1 -1
@@ -1002,7 +1002,7 @@ static const struct of_device_id ina3221_of_match_table[] = {MODULE_DEVICE_TABLE (of, ina3221_of_match_table);static const struct i2c_device_id ina3221_ids[] = { - {"ina3221" }, + { .name ="ina3221" }, {/* sentinel */ } };MODULE_DEVICE_TABLE (i2c, ina3221_ids);
drivers/hwmon/isl28022.c +1 -1
@@ -475,7 +475,7 @@ static int isl28022_probe(struct i2c_client *client) }static const struct i2c_device_id isl28022_ids[] = { - {"isl28022" }, + { .name ="isl28022" }, {/* LIST END */ } };MODULE_DEVICE_TABLE (i2c, isl28022_ids);
drivers/hwmon/jc42.c +1 -1
@@ -579,7 +579,7 @@ static const struct dev_pm_ops jc42_dev_pm_ops = {#endif /* CONFIG_PM */ static const struct i2c_device_id jc42_id[] = { - {"jc42" }, + { .name ="jc42" }, { } };MODULE_DEVICE_TABLE (i2c, jc42_id);
drivers/hwmon/lineage-pem.c +2 -2
@@ -502,8 +502,8 @@ static int pem_probe(struct i2c_client *client) }static const struct i2c_device_id pem_id[] = { - {"lineage_pem" }, - {} + { .name ="lineage_pem" }, + { } };MODULE_DEVICE_TABLE (i2c, pem_id);
drivers/hwmon/lm63.c +3 -3
@@ -1152,9 +1152,9 @@ static int lm63_probe(struct i2c_client *client)*/ static const struct i2c_device_id lm63_id[] = { - {"lm63" , lm63 }, - {"lm64" , lm64 }, - {"lm96163" , lm96163 }, + { .name ="lm63" , .driver_data = lm63 }, + { .name ="lm64" , .driver_data = lm64 }, + { .name ="lm96163" , .driver_data = lm96163 }, { } };MODULE_DEVICE_TABLE (i2c, lm63_id);
drivers/hwmon/lm73.c +1 -1
@@ -220,7 +220,7 @@ lm73_probe(struct i2c_client *client) }static const struct i2c_device_id lm73_ids[] = { - {"lm73" }, + { .name ="lm73" }, {/* LIST END */ } };MODULE_DEVICE_TABLE (i2c, lm73_ids);
drivers/hwmon/lm75.c +31 -31
68 lines not on this page · raw message
drivers/hwmon/lm77.c +1 -1
@@ -337,7 +337,7 @@ static int lm77_probe(struct i2c_client *client) }static const struct i2c_device_id lm77_id[] = { - {"lm77" }, + { .name ="lm77" }, { } };MODULE_DEVICE_TABLE (i2c, lm77_id);
drivers/hwmon/lm78.c +2 -2
@@ -649,8 +649,8 @@ static int lm78_i2c_probe(struct i2c_client *client) }static const struct i2c_device_id lm78_i2c_id[] = { - {"lm78" , lm78 }, - {"lm79" , lm79 }, + { .name ="lm78" , .driver_data = lm78 }, + { .name ="lm79" , .driver_data = lm79 }, { } };MODULE_DEVICE_TABLE (i2c, lm78_i2c_id);
drivers/hwmon/lm80.c +2 -2
@@ -622,8 +622,8 @@ static int lm80_probe(struct i2c_client *client)*/ static const struct i2c_device_id lm80_id[] = { - {"lm80" }, - {"lm96080" }, + { .name ="lm80" }, + { .name ="lm96080" }, { } };MODULE_DEVICE_TABLE (i2c, lm80_id);
drivers/hwmon/lm83.c +2 -2
@@ -443,8 +443,8 @@ static int lm83_probe(struct i2c_client *client)*/ static const struct i2c_device_id lm83_id[] = { - {"lm83" , lm83 }, - {"lm82" , lm82 }, + { .name ="lm83" , .driver_data = lm83 }, + { .name ="lm82" , .driver_data = lm82 }, { } };MODULE_DEVICE_TABLE (i2c, lm83_id);
drivers/hwmon/lm85.c +12 -12
@@ -1618,18 +1618,18 @@ static int lm85_probe(struct i2c_client *client) }static const struct i2c_device_id lm85_id[] = { - {"adm1027" , adm1027 }, - {"adt7463" , adt7463 }, - {"adt7468" , adt7468 }, - {"lm85" , lm85 }, - {"lm85b" , lm85 }, - {"lm85c" , lm85 }, - {"lm96000" , lm96000 }, - {"emc6d100" , emc6d100 }, - {"emc6d101" , emc6d100 }, - {"emc6d102" , emc6d102 }, - {"emc6d103" , emc6d103 }, - {"emc6d103s" , emc6d103s }, + { .name ="adm1027" , .driver_data = adm1027 }, + { .name ="adt7463" , .driver_data = adt7463 }, + { .name ="adt7468" , .driver_data = adt7468 }, + { .name ="lm85" , .driver_data = lm85 }, + { .name ="lm85b" , .driver_data = lm85 }, + { .name ="lm85c" , .driver_data = lm85 }, + { .name ="lm96000" , .driver_data = lm96000 }, + { .name ="emc6d100" , .driver_data = emc6d100 }, + { .name ="emc6d101" , .driver_data = emc6d100 }, + { .name ="emc6d102" , .driver_data = emc6d102 }, + { .name ="emc6d103" , .driver_data = emc6d103 }, + { .name ="emc6d103s" , .driver_data = emc6d103s }, { } };MODULE_DEVICE_TABLE (i2c, lm85_id);
drivers/hwmon/lm87.c +2 -2
@@ -981,8 +981,8 @@ static int lm87_probe(struct i2c_client *client)*/ static const struct i2c_device_id lm87_id[] = { - {"lm87" }, - {"adm1024" }, + { .name ="lm87" }, + { .name ="adm1024" }, { } };MODULE_DEVICE_TABLE (i2c, lm87_id);
drivers/hwmon/lm90.c +48 -48
102 lines not on this page · raw message
drivers/hwmon/lm92.c +3 -3
@@ -405,10 +405,10 @@ static int lm92_probe(struct i2c_client *client)* Module and driver stuff */ -/* .driver_data is limit register resolution */ +/* .driver_data is limit register resolution */ static const struct i2c_device_id lm92_id[] = { - {"lm92" ,13 }, - {"max6635" ,9 }, + { .name ="lm92" , .driver_data =13 }, + { .name ="max6635" , .driver_data =9 }, { } };MODULE_DEVICE_TABLE (i2c, lm92_id);
drivers/hwmon/lm93.c +2 -2
@@ -2624,8 +2624,8 @@ static int lm93_probe(struct i2c_client *client) }static const struct i2c_device_id lm93_id[] = { - {"lm93" }, - {"lm94" }, + { .name ="lm93" }, + { .name ="lm94" }, { } };MODULE_DEVICE_TABLE (i2c, lm93_id);
drivers/hwmon/lm95234.c +2 -2
@@ -532,8 +532,8 @@ static int lm95234_probe(struct i2c_client *client)/* Driver data (common to all clients) */ static const struct i2c_device_id lm95234_id[] = { - {"lm95233" , lm95233 }, - {"lm95234" , lm95234 }, + { .name ="lm95233" , .driver_data = lm95233 }, + { .name ="lm95234" , .driver_data = lm95234 }, { } };MODULE_DEVICE_TABLE (i2c, lm95234_id);
drivers/hwmon/lm95241.c +2 -2
@@ -441,8 +441,8 @@ static int lm95241_probe(struct i2c_client *client)/* Driver data (common to all clients) */ static const struct i2c_device_id lm95241_id[] = { - {"lm95231" }, - {"lm95241" }, + { .name ="lm95231" }, + { .name ="lm95241" }, { } };MODULE_DEVICE_TABLE (i2c, lm95241_id);
drivers/hwmon/lm95245.c +2 -2
@@ -546,8 +546,8 @@ static int lm95245_probe(struct i2c_client *client)/* Driver data (common to all clients) */ static const struct i2c_device_id lm95245_id[] = { - {"lm95235" }, - {"lm95245" }, + { .name ="lm95235" }, + { .name ="lm95245" }, { } };MODULE_DEVICE_TABLE (i2c, lm95245_id);
drivers/hwmon/ltc2945.c +1 -1
@@ -508,7 +508,7 @@ static int ltc2945_probe(struct i2c_client *client) }static const struct i2c_device_id ltc2945_id[] = { - {"ltc2945" }, + { .name ="ltc2945" }, { } };
drivers/hwmon/ltc2947-i2c.c +2 -2
@@ -27,8 +27,8 @@ static int ltc2947_probe(struct i2c_client *i2c) }static const struct i2c_device_id ltc2947_id[] = { - {"ltc2947" }, - {} + { .name ="ltc2947" }, + { } };MODULE_DEVICE_TABLE (i2c, ltc2947_id);
drivers/hwmon/ltc2990.c +2 -2
@@ -259,8 +259,8 @@ static int ltc2990_i2c_probe(struct i2c_client *i2c) }static const struct i2c_device_id ltc2990_i2c_id[] = { - {"ltc2990" }, - {} + { .name ="ltc2990" }, + { } };MODULE_DEVICE_TABLE (i2c, ltc2990_i2c_id);
drivers/hwmon/ltc2991.c +2 -2
@@ -409,8 +409,8 @@ static const struct of_device_id ltc2991_of_match[] = {MODULE_DEVICE_TABLE (of, ltc2991_of_match);static const struct i2c_device_id ltc2991_i2c_id[] = { - {"ltc2991" }, - {} + { .name ="ltc2991" }, + { } };MODULE_DEVICE_TABLE (i2c, ltc2991_i2c_id);
drivers/hwmon/ltc2992.c +2 -2
@@ -948,8 +948,8 @@ static const struct of_device_id ltc2992_of_match[] = {MODULE_DEVICE_TABLE (of, ltc2992_of_match);static const struct i2c_device_id ltc2992_i2c_id[] = { - {"ltc2992" }, - {} + { .name ="ltc2992" }, + { } };MODULE_DEVICE_TABLE (i2c, ltc2992_i2c_id);
drivers/hwmon/ltc4151.c +1 -1
@@ -188,7 +188,7 @@ static int ltc4151_probe(struct i2c_client *client) }static const struct i2c_device_id ltc4151_id[] = { - {"ltc4151" }, + { .name ="ltc4151" }, { } };MODULE_DEVICE_TABLE (i2c, ltc4151_id);
drivers/hwmon/ltc4215.c +1 -1
@@ -245,7 +245,7 @@ static int ltc4215_probe(struct i2c_client *client) }static const struct i2c_device_id ltc4215_id[] = { - {"ltc4215" }, + { .name ="ltc4215" }, { } };MODULE_DEVICE_TABLE (i2c, ltc4215_id);
drivers/hwmon/ltc4222.c +1 -1
@@ -200,7 +200,7 @@ static int ltc4222_probe(struct i2c_client *client) }static const struct i2c_device_id ltc4222_id[] = { - {"ltc4222" }, + { .name ="ltc4222" }, { } };
drivers/hwmon/ltc4245.c +1 -1
@@ -461,7 +461,7 @@ static int ltc4245_probe(struct i2c_client *client) }static const struct i2c_device_id ltc4245_id[] = { - {"ltc4245" }, + { .name ="ltc4245" }, { } };MODULE_DEVICE_TABLE (i2c, ltc4245_id);
drivers/hwmon/ltc4260.c +1 -1
@@ -163,7 +163,7 @@ static int ltc4260_probe(struct i2c_client *client) }static const struct i2c_device_id ltc4260_id[] = { - {"ltc4260" }, + { .name ="ltc4260" }, { } };
drivers/hwmon/ltc4261.c +2 -2
@@ -222,8 +222,8 @@ static int ltc4261_probe(struct i2c_client *client) }static const struct i2c_device_id ltc4261_id[] = { - {"ltc4261" }, - {} + { .name ="ltc4261" }, + { } };MODULE_DEVICE_TABLE (i2c, ltc4261_id);
drivers/hwmon/max127.c +1 -1
@@ -312,7 +312,7 @@ static int max127_probe(struct i2c_client *client) }static const struct i2c_device_id max127_id[] = { - {"max127" }, + { .name ="max127" }, { } };MODULE_DEVICE_TABLE (i2c, max127_id);
drivers/hwmon/max16065.c +6 -6
@@ -592,12 +592,12 @@ static int max16065_probe(struct i2c_client *client) }static const struct i2c_device_id max16065_id[] = { - {"max16065" , max16065 }, - {"max16066" , max16066 }, - {"max16067" , max16067 }, - {"max16068" , max16068 }, - {"max16070" , max16070 }, - {"max16071" , max16071 }, + { .name ="max16065" , .driver_data = max16065 }, + { .name ="max16066" , .driver_data = max16066 }, + { .name ="max16067" , .driver_data = max16067 }, + { .name ="max16068" , .driver_data = max16068 }, + { .name ="max16070" , .driver_data = max16070 }, + { .name ="max16071" , .driver_data = max16071 }, { } };
drivers/hwmon/max1619.c +1 -1
@@ -366,7 +366,7 @@ static int max1619_probe(struct i2c_client *client) }static const struct i2c_device_id max1619_id[] = { - {"max1619" }, + { .name ="max1619" }, { } };MODULE_DEVICE_TABLE (i2c, max1619_id);
drivers/hwmon/max1668.c +3 -3
@@ -293,9 +293,9 @@ static int max1668_probe(struct i2c_client *client) }static const struct i2c_device_id max1668_id[] = { - {"max1668" ,5 }, - {"max1805" ,3 }, - {"max1989" ,5 }, + { .name ="max1668" , .driver_data =5 }, + { .name ="max1805" , .driver_data =3 }, + { .name ="max1989" , .driver_data =5 }, { } };MODULE_DEVICE_TABLE (i2c, max1668_id);
drivers/hwmon/max31730.c +1 -1
@@ -345,7 +345,7 @@ max31730_probe(struct i2c_client *client) }static const struct i2c_device_id max31730_ids[] = { - {"max31730" }, + { .name ="max31730" }, { } };MODULE_DEVICE_TABLE (i2c, max31730_ids);
drivers/hwmon/max31760.c +1 -1
@@ -555,7 +555,7 @@ static const struct of_device_id max31760_of_match[] = {MODULE_DEVICE_TABLE (of, max31760_of_match);static const struct i2c_device_id max31760_id[] = { - {"max31760" }, + { .name ="max31760" }, { } };MODULE_DEVICE_TABLE (i2c, max31760_id);
drivers/hwmon/max31790.c +1 -1
@@ -517,7 +517,7 @@ static int max31790_probe(struct i2c_client *client) }static const struct i2c_device_id max31790_id[] = { - {"max31790" }, + { .name ="max31790" }, { } };MODULE_DEVICE_TABLE (i2c, max31790_id);
drivers/hwmon/max31827.c +3 -3
@@ -463,9 +463,9 @@ static struct attribute *max31827_attrs[] = {ATTRIBUTE_GROUPS (max31827);static const struct i2c_device_id max31827_i2c_ids[] = { - {"max31827" , max31827 }, - {"max31828" , max31828 }, - {"max31829" , max31829 }, + { .name ="max31827" , .driver_data = max31827 }, + { .name ="max31828" , .driver_data = max31828 }, + { .name ="max31829" , .driver_data = max31829 }, { } };MODULE_DEVICE_TABLE (i2c, max31827_i2c_ids);
drivers/hwmon/max6620.c +1 -1
@@ -474,7 +474,7 @@ static int max6620_probe(struct i2c_client *client) }static const struct i2c_device_id max6620_id[] = { - {"max6620" }, + { .name ="max6620" }, { } };MODULE_DEVICE_TABLE (i2c, max6620_id);
drivers/hwmon/max6621.c +1 -1
@@ -537,7 +537,7 @@ static int max6621_probe(struct i2c_client *client) }static const struct i2c_device_id max6621_id[] = { - {MAX6621_DRV_NAME }, + { .name =MAX6621_DRV_NAME }, { } };MODULE_DEVICE_TABLE (i2c, max6621_id);
drivers/hwmon/max6639.c +1 -1
@@ -778,7 +778,7 @@ static int max6639_resume(struct device *dev) }static const struct i2c_device_id max6639_id[] = { - {"max6639" }, + { .name ="max6639" }, { } };
drivers/hwmon/max6650.c +2 -2
@@ -807,8 +807,8 @@ static int max6650_probe(struct i2c_client *client) }static const struct i2c_device_id max6650_id[] = { - {"max6650" ,1 }, - {"max6651" ,4 }, + { .name ="max6650" , .driver_data =1 }, + { .name ="max6651" , .driver_data =4 }, { } };MODULE_DEVICE_TABLE (i2c, max6650_id);
drivers/hwmon/max6697.c +10 -10
@@ -564,16 +564,16 @@ static int max6697_probe(struct i2c_client *client) }static const struct i2c_device_id max6697_id[] = { - {"max6581" , max6581 }, - {"max6602" , max6602 }, - {"max6622" , max6622 }, - {"max6636" , max6636 }, - {"max6689" , max6689 }, - {"max6693" , max6693 }, - {"max6694" , max6694 }, - {"max6697" , max6697 }, - {"max6698" , max6698 }, - {"max6699" , max6699 }, + { .name ="max6581" , .driver_data = max6581 }, + { .name ="max6602" , .driver_data = max6602 }, + { .name ="max6622" , .driver_data = max6622 }, + { .name ="max6636" , .driver_data = max6636 }, + { .name ="max6689" , .driver_data = max6689 }, + { .name ="max6693" , .driver_data = max6693 }, + { .name ="max6694" , .driver_data = max6694 }, + { .name ="max6697" , .driver_data = max6697 }, + { .name ="max6698" , .driver_data = max6698 }, + { .name ="max6699" , .driver_data = max6699 }, { } };MODULE_DEVICE_TABLE (i2c, max6697_id);
drivers/hwmon/mc34vr500.c +2 -2
@@ -235,8 +235,8 @@ static int mc34vr500_probe(struct i2c_client *client) }static const struct i2c_device_id mc34vr500_id[] = { - {"mc34vr500" }, - { }, + { .name ="mc34vr500" }, + { } };MODULE_DEVICE_TABLE (i2c, mc34vr500_id);
drivers/hwmon/mcp3021.c +2 -2
@@ -177,8 +177,8 @@ static int mcp3021_probe(struct i2c_client *client) }static const struct i2c_device_id mcp3021_id[] = { - {"mcp3021" , mcp3021 }, - {"mcp3221" , mcp3221 }, + { .name ="mcp3021" , .driver_data = mcp3021 }, + { .name ="mcp3221" , .driver_data = mcp3221 }, { } };MODULE_DEVICE_TABLE (i2c, mcp3021_id);
drivers/hwmon/nct6775-i2c.c +13 -13
@@ -93,19 +93,19 @@ static const struct of_device_id __maybe_unused nct6775_i2c_of_match[] = {MODULE_DEVICE_TABLE (of, nct6775_i2c_of_match);static const struct i2c_device_id nct6775_i2c_id[] = { - {"nct6106" , nct6106 }, - {"nct6116" , nct6116 }, - {"nct6775" , nct6775 }, - {"nct6776" , nct6776 }, - {"nct6779" , nct6779 }, - {"nct6791" , nct6791 }, - {"nct6792" , nct6792 }, - {"nct6793" , nct6793 }, - {"nct6795" , nct6795 }, - {"nct6796" , nct6796 }, - {"nct6797" , nct6797 }, - {"nct6798" , nct6798 }, - {"nct6799" , nct6799 }, + { .name ="nct6106" , .driver_data = nct6106 }, + { .name ="nct6116" , .driver_data = nct6116 }, + { .name ="nct6775" , .driver_data = nct6775 }, + { .name ="nct6776" , .driver_data = nct6776 }, + { .name ="nct6779" , .driver_data = nct6779 }, + { .name ="nct6791" , .driver_data = nct6791 }, + { .name ="nct6792" , .driver_data = nct6792 }, + { .name ="nct6793" , .driver_data = nct6793 }, + { .name ="nct6795" , .driver_data = nct6795 }, + { .name ="nct6796" , .driver_data = nct6796 }, + { .name ="nct6797" , .driver_data = nct6797 }, + { .name ="nct6798" , .driver_data = nct6798 }, + { .name ="nct6799" , .driver_data = nct6799 }, { } };MODULE_DEVICE_TABLE (i2c, nct6775_i2c_id);
drivers/hwmon/nct7802.c +1 -1
@@ -1193,7 +1193,7 @@ static const unsigned short nct7802_address_list[] = { };static const struct i2c_device_id nct7802_idtable[] = { - {"nct7802" }, + { .name ="nct7802" }, { } };MODULE_DEVICE_TABLE (i2c, nct7802_idtable);
drivers/hwmon/nct7904.c +2 -2
@@ -1146,8 +1146,8 @@ static int nct7904_probe(struct i2c_client *client) }static const struct i2c_device_id nct7904_id[] = { - {"nct7904" }, - {} + { .name ="nct7904" }, + { } };MODULE_DEVICE_TABLE (i2c, nct7904_id);
drivers/hwmon/pcf8591.c +1 -1
@@ -285,7 +285,7 @@ static int pcf8591_read_channel(struct device *dev, int channel) }static const struct i2c_device_id pcf8591_id[] = { - {"pcf8591" }, + { .name ="pcf8591" }, { } };MODULE_DEVICE_TABLE (i2c, pcf8591_id);
drivers/hwmon/pmbus/acbel-fsg032.c +2 -2
@@ -49,8 +49,8 @@ static void acbel_fsg032_init_debugfs(struct i2c_client *client) }static const struct i2c_device_id acbel_fsg032_id[] = { - {"acbel_fsg032" }, - {} + { .name ="acbel_fsg032" }, + { } };static struct pmbus_driver_info acbel_fsg032_info = {
drivers/hwmon/pmbus/adm1266.c +1 -1
@@ -510,7 +510,7 @@ static const struct of_device_id adm1266_of_match[] = {MODULE_DEVICE_TABLE (of, adm1266_of_match);static const struct i2c_device_id adm1266_id[] = { - {"adm1266" }, + { .name ="adm1266" }, { } };MODULE_DEVICE_TABLE (i2c, adm1266_id);
drivers/hwmon/pmbus/adm1275.c +10 -10
@@ -478,16 +478,16 @@ static int adm1275_read_byte_data(struct i2c_client *client, int page, int reg) }static const struct i2c_device_id adm1275_id[] = { - {"adm1075" , adm1075 }, - {"adm1272" , adm1272 }, - {"adm1273" , adm1273 }, - {"adm1275" , adm1275 }, - {"adm1276" , adm1276 }, - {"adm1278" , adm1278 }, - {"adm1281" , adm1281 }, - {"adm1293" , adm1293 }, - {"adm1294" , adm1294 }, - {"mc09c" , sq24905c }, + { .name ="adm1075" , .driver_data = adm1075 }, + { .name ="adm1272" , .driver_data = adm1272 }, + { .name ="adm1273" , .driver_data = adm1273 }, + { .name ="adm1275" , .driver_data = adm1275 }, + { .name ="adm1276" , .driver_data = adm1276 }, + { .name ="adm1278" , .driver_data = adm1278 }, + { .name ="adm1281" , .driver_data = adm1281 }, + { .name ="adm1293" , .driver_data = adm1293 }, + { .name ="adm1294" , .driver_data = adm1294 }, + { .name ="mc09c" , .driver_data = sq24905c }, { } };MODULE_DEVICE_TABLE (i2c, adm1275_id);
drivers/hwmon/pmbus/bel-pfe.c +3 -3
@@ -106,9 +106,9 @@ static int pfe_pmbus_probe(struct i2c_client *client) }static const struct i2c_device_id pfe_device_id[] = { - {"pfe1100" , pfe1100}, - {"pfe3000" , pfe3000}, - {} + { .name ="pfe1100" , .driver_data = pfe1100 }, + { .name ="pfe3000" , .driver_data = pfe3000 }, + { } };MODULE_DEVICE_TABLE (i2c, pfe_device_id);
drivers/hwmon/pmbus/bpa-rs600.c +3 -3
@@ -147,9 +147,9 @@ static struct pmbus_driver_info bpa_rs600_info = { };static const struct i2c_device_id bpa_rs600_id[] = { - {"bpa-rs600" , bpa_rs600 }, - {"bpd-rs600" , bpd_rs600 }, - {}, + { .name ="bpa-rs600" , .driver_data = bpa_rs600 }, + { .name ="bpd-rs600" , .driver_data = bpd_rs600 }, + { } };MODULE_DEVICE_TABLE (i2c, bpa_rs600_id);
drivers/hwmon/pmbus/crps.c +2 -2
@@ -10,8 +10,8 @@#include "pmbus.h" static const struct i2c_device_id crps_id[] = { - {"intel_crps185" }, - {} + { .name ="intel_crps185" }, + { } };MODULE_DEVICE_TABLE (i2c, crps_id);
drivers/hwmon/pmbus/delta-ahe50dc-fan.c +1 -1
@@ -103,7 +103,7 @@ static int ahe50dc_fan_probe(struct i2c_client *client) }static const struct i2c_device_id ahe50dc_fan_id[] = { - {"ahe50dc_fan" }, + { .name ="ahe50dc_fan" }, { } };MODULE_DEVICE_TABLE (i2c, ahe50dc_fan_id);
drivers/hwmon/pmbus/dps920ab.c +2 -2
@@ -191,8 +191,8 @@ static const struct of_device_id __maybe_unused dps920ab_of_match[] = {MODULE_DEVICE_TABLE (of, dps920ab_of_match);static const struct i2c_device_id dps920ab_device_id[] = { - {"dps920ab" }, - {} + { .name ="dps920ab" }, + { } };MODULE_DEVICE_TABLE (i2c, dps920ab_device_id);
drivers/hwmon/pmbus/fsp-3y.c +2 -2
@@ -271,8 +271,8 @@ static int fsp3y_probe(struct i2c_client *client) }static const struct i2c_device_id fsp3y_id[] = { - {"ym2151e" , ym2151e}, - {"yh5151e" , yh5151e}, + { .name ="ym2151e" , .driver_data = ym2151e }, + { .name ="yh5151e" , .driver_data = yh5151e }, { } };MODULE_DEVICE_TABLE (i2c, fsp3y_id);
drivers/hwmon/pmbus/hac300s.c +2 -2
@@ -112,8 +112,8 @@ static const struct of_device_id hac300s_of_match[] = {MODULE_DEVICE_TABLE (of, hac300s_of_match);static const struct i2c_device_id hac300s_id[] = { - {"hac300s" ,0 }, - {} + { .name ="hac300s" }, + { } };MODULE_DEVICE_TABLE (i2c, hac300s_id);
drivers/hwmon/pmbus/ibm-cffps.c +4 -4
@@ -472,10 +472,10 @@ static struct pmbus_platform_data ibm_cffps_pdata = { };static const struct i2c_device_id ibm_cffps_id[] = { - {"ibm_cffps1" , cffps1 }, - {"ibm_cffps2" , cffps2 }, - {"ibm_cffps" , cffps_unknown }, - {} + { .name ="ibm_cffps1" , .driver_data = cffps1 }, + { .name ="ibm_cffps2" , .driver_data = cffps2 }, + { .name ="ibm_cffps" , .driver_data = cffps_unknown }, + { } };MODULE_DEVICE_TABLE (i2c, ibm_cffps_id);
drivers/hwmon/pmbus/ina233.c +2 -2
@@ -168,8 +168,8 @@ static int ina233_probe(struct i2c_client *client) }static const struct i2c_device_id ina233_id[] = { - {"ina233" ,0 }, - {} + { .name ="ina233" }, + { } };MODULE_DEVICE_TABLE (i2c, ina233_id);
drivers/hwmon/pmbus/inspur-ipsps.c +2 -2
@@ -197,8 +197,8 @@ static int ipsps_probe(struct i2c_client *client) }static const struct i2c_device_id ipsps_id[] = { - {"ipsps1" }, - {} + { .name ="ipsps1" }, + { } };MODULE_DEVICE_TABLE (i2c, ipsps_id);
drivers/hwmon/pmbus/ir35221.c +2 -2
@@ -126,8 +126,8 @@ static int ir35221_probe(struct i2c_client *client) }static const struct i2c_device_id ir35221_id[] = { - {"ir35221" }, - {} + { .name ="ir35221" }, + { } };MODULE_DEVICE_TABLE (i2c, ir35221_id);
drivers/hwmon/pmbus/ir36021.c +2 -2
@@ -51,8 +51,8 @@ static int ir36021_probe(struct i2c_client *client) }static const struct i2c_device_id ir36021_id[] = { - {"ir36021" }, - {}, + { .name ="ir36021" }, + { } };MODULE_DEVICE_TABLE (i2c, ir36021_id);
drivers/hwmon/pmbus/ir38064.c +5 -5
@@ -53,11 +53,11 @@ static int ir38064_probe(struct i2c_client *client) }static const struct i2c_device_id ir38064_id[] = { - {"ir38060" }, - {"ir38064" }, - {"ir38164" }, - {"ir38263" }, - {} + { .name ="ir38060" }, + { .name ="ir38064" }, + { .name ="ir38164" }, + { .name ="ir38263" }, + { } };MODULE_DEVICE_TABLE (i2c, ir38064_id);
drivers/hwmon/pmbus/irps5401.c +2 -2
@@ -44,8 +44,8 @@ static int irps5401_probe(struct i2c_client *client) }static const struct i2c_device_id irps5401_id[] = { - {"irps5401" }, - {} + { .name ="irps5401" }, + { } };MODULE_DEVICE_TABLE (i2c, irps5401_id);
drivers/hwmon/pmbus/isl68137.c +48 -48
102 lines not on this page · raw message
drivers/hwmon/pmbus/lm25066.c +5 -5
@@ -442,11 +442,11 @@ static const struct regulator_desc lm25066_reg_desc[] = {#endif static const struct i2c_device_id lm25066_id[] = { - {"lm25056" , lm25056}, - {"lm25066" , lm25066}, - {"lm5064" , lm5064}, - {"lm5066" , lm5066}, - {"lm5066i" , lm5066i}, + { .name ="lm25056" , .driver_data = lm25056 }, + { .name ="lm25066" , .driver_data = lm25066 }, + { .name ="lm5064" , .driver_data = lm5064 }, + { .name ="lm5066" , .driver_data = lm5066 }, + { .name ="lm5066i" , .driver_data = lm5066i }, { } };MODULE_DEVICE_TABLE (i2c, lm25066_id);
drivers/hwmon/pmbus/lt7182s.c +2 -2
@@ -168,8 +168,8 @@ static int lt7182s_probe(struct i2c_client *client) }static const struct i2c_device_id lt7182s_id[] = { - {"lt7182s" }, - {} + { .name ="lt7182s" }, + { } };MODULE_DEVICE_TABLE (i2c, lt7182s_id);
drivers/hwmon/pmbus/ltc2978.c +30 -30
66 lines not on this page · raw message
drivers/hwmon/pmbus/ltc3815.c +1 -1
@@ -143,7 +143,7 @@ static int ltc3815_write_word_data(struct i2c_client *client, int page, }static const struct i2c_device_id ltc3815_id[] = { - {"ltc3815" }, + { .name ="ltc3815" }, { } };MODULE_DEVICE_TABLE (i2c, ltc3815_id);
drivers/hwmon/pmbus/max15301.c +4 -4
@@ -23,10 +23,10 @@#include "pmbus.h" static const struct i2c_device_id max15301_id[] = { - {"bmr461" }, - {"max15301" }, - {"max15303" }, - {} + { .name ="bmr461" }, + { .name ="max15301" }, + { .name ="max15303" }, + { } };MODULE_DEVICE_TABLE (i2c, max15301_id);
drivers/hwmon/pmbus/max16064.c +2 -2
@@ -91,8 +91,8 @@ static int max16064_probe(struct i2c_client *client) }static const struct i2c_device_id max16064_id[] = { - {"max16064" }, - {} + { .name ="max16064" }, + { } };MODULE_DEVICE_TABLE (i2c, max16064_id);
drivers/hwmon/pmbus/max16601.c +5 -5
@@ -263,11 +263,11 @@ static void max16601_remove(void *_data) }static const struct i2c_device_id max16601_id[] = { - {"max16508" , max16508}, - {"max16600" , max16600}, - {"max16601" , max16601}, - {"max16602" , max16602}, - {} + { .name ="max16508" , .driver_data = max16508 }, + { .name ="max16600" , .driver_data = max16600 }, + { .name ="max16601" , .driver_data = max16601 }, + { .name ="max16602" , .driver_data = max16602 }, + { } };MODULE_DEVICE_TABLE (i2c, max16601_id);
drivers/hwmon/pmbus/max17616.c +1 -1
@@ -46,7 +46,7 @@ static int max17616_probe(struct i2c_client *client) }static const struct i2c_device_id max17616_id[] = { - {"max17616" }, + { .name ="max17616" }, { } };MODULE_DEVICE_TABLE (i2c, max17616_id);
drivers/hwmon/pmbus/max20730.c +5 -5
@@ -751,11 +751,11 @@ static int max20730_probe(struct i2c_client *client) }static const struct i2c_device_id max20730_id[] = { - {"max20710" , max20710 }, - {"max20730" , max20730 }, - {"max20734" , max20734 }, - {"max20743" , max20743 }, - { }, + { .name ="max20710" , .driver_data = max20710 }, + { .name ="max20730" , .driver_data = max20730 }, + { .name ="max20734" , .driver_data = max20734 }, + { .name ="max20743" , .driver_data = max20743 }, + { } };MODULE_DEVICE_TABLE (i2c, max20730_id);
drivers/hwmon/pmbus/max20751.c +2 -2
@@ -32,8 +32,8 @@ static int max20751_probe(struct i2c_client *client) }static const struct i2c_device_id max20751_id[] = { - {"max20751" }, - {} + { .name ="max20751" }, + { } };MODULE_DEVICE_TABLE (i2c, max20751_id);
drivers/hwmon/pmbus/max31785.c +4 -4
@@ -447,10 +447,10 @@ static int max31785_probe(struct i2c_client *client) }static const struct i2c_device_id max31785_id[] = { - {"max31785" }, - {"max31785a" }, - {"max31785b" }, - { }, + { .name ="max31785" }, + { .name ="max31785a" }, + { .name ="max31785b" }, + { } };MODULE_DEVICE_TABLE (i2c, max31785_id);
drivers/hwmon/pmbus/max34440.c +9 -9
@@ -644,15 +644,15 @@ static int max34440_probe(struct i2c_client *client) }static const struct i2c_device_id max34440_id[] = { - {"adpm12160" , adpm12160}, - {"adpm12200" , adpm12200}, - {"max34440" , max34440}, - {"max34441" , max34441}, - {"max34446" , max34446}, - {"max34451" , max34451}, - {"max34460" , max34460}, - {"max34461" , max34461}, - {} + { .name ="adpm12160" , .driver_data = adpm12160 }, + { .name ="adpm12200" , .driver_data = adpm12200 }, + { .name ="max34440" , .driver_data = max34440 }, + { .name ="max34441" , .driver_data = max34441 }, + { .name ="max34446" , .driver_data = max34446 }, + { .name ="max34451" , .driver_data = max34451 }, + { .name ="max34460" , .driver_data = max34460 }, + { .name ="max34461" , .driver_data = max34461 }, + { } };MODULE_DEVICE_TABLE (i2c, max34440_id);
drivers/hwmon/pmbus/max8688.c +1 -1
@@ -171,7 +171,7 @@ static int max8688_probe(struct i2c_client *client) }static const struct i2c_device_id max8688_id[] = { - {"max8688" }, + { .name ="max8688" }, { } };
drivers/hwmon/pmbus/mp2856.c +3 -3
@@ -54,9 +54,9 @@ static const int mp2856_max_phases[][MP2856_PAGE_NUM] = { };static const struct i2c_device_id mp2856_id[] = { - {"mp2856" , mp2856}, - {"mp2857" , mp2857}, - {} + { .name ="mp2856" , .driver_data = mp2856 }, + { .name ="mp2857" , .driver_data = mp2857 }, + { } };MODULE_DEVICE_TABLE (i2c, mp2856_id);
drivers/hwmon/pmbus/mp2888.c +2 -2
@@ -378,8 +378,8 @@ static int mp2888_probe(struct i2c_client *client) }static const struct i2c_device_id mp2888_id[] = { - {"mp2888" }, - {} + { .name ="mp2888" }, + { } };MODULE_DEVICE_TABLE (i2c, mp2888_id);
drivers/hwmon/pmbus/mp2891.c +1 -1
@@ -572,7 +572,7 @@ static int mp2891_probe(struct i2c_client *client) }static const struct i2c_device_id mp2891_id[] = { - {"mp2891" }, + { .name ="mp2891" }, { } };MODULE_DEVICE_TABLE (i2c, mp2891_id);
drivers/hwmon/pmbus/mp2925.c +3 -3
@@ -305,9 +305,9 @@ static int mp2925_probe(struct i2c_client *client) }static const struct i2c_device_id mp2925_id[] = { - {"mp2925" }, - {"mp2929" }, - {} + { .name ="mp2925" }, + { .name ="mp2929" }, + { } };MODULE_DEVICE_TABLE (i2c, mp2925_id);
drivers/hwmon/pmbus/mp29502.c +2 -2
@@ -642,8 +642,8 @@ static int mp29502_probe(struct i2c_client *client) }static const struct i2c_device_id mp29502_id[] = { - {"mp29502" ,0 }, - {} + { .name ="mp29502" , .driver_data =0 }, + { } };MODULE_DEVICE_TABLE (i2c, mp29502_id);
drivers/hwmon/pmbus/mp2975.c +4 -4
@@ -1082,10 +1082,10 @@ static const struct of_device_id mp2975_of_match[] = {MODULE_DEVICE_TABLE (of, mp2975_of_match);static const struct i2c_device_id mp2975_id[] = { - {"mp2971" , (kernel_ulong_t)&mp2975_ddinfo[mp2971]}, - {"mp2973" , (kernel_ulong_t)&mp2975_ddinfo[mp2973]}, - {"mp2975" , (kernel_ulong_t)&mp2975_ddinfo[mp2975]}, - {} + { .name ="mp2971" , .driver_data = (kernel_ulong_t)&mp2975_ddinfo[mp2971] }, + { .name ="mp2973" , .driver_data = (kernel_ulong_t)&mp2975_ddinfo[mp2973] }, + { .name ="mp2975" , .driver_data = (kernel_ulong_t)&mp2975_ddinfo[mp2975] }, + { } };MODULE_DEVICE_TABLE (i2c, mp2975_id);
drivers/hwmon/pmbus/mp2993.c +1 -1
@@ -233,7 +233,7 @@ static int mp2993_probe(struct i2c_client *client) }static const struct i2c_device_id mp2993_id[] = { - {"mp2993" }, + { .name ="mp2993" }, { } };MODULE_DEVICE_TABLE (i2c, mp2993_id);
drivers/hwmon/pmbus/mp5920.c +1 -1
@@ -66,7 +66,7 @@ static const struct of_device_id mp5920_of_match[] = {MODULE_DEVICE_TABLE (of, mp5920_of_match);static const struct i2c_device_id mp5920_id[] = { - {"mp5920" }, + { .name ="mp5920" }, { } };
drivers/hwmon/pmbus/mp5926.c +2 -2
@@ -157,8 +157,8 @@ static int mp5926_probe(struct i2c_client *client) }static const struct i2c_device_id mp5926_id[] = { - {"mp5926" ,0 }, - {} + { .name ="mp5926" , .driver_data =0 }, + { } };MODULE_DEVICE_TABLE (i2c, mp5926_id);
drivers/hwmon/pmbus/mp5990.c +2 -2
@@ -148,8 +148,8 @@ static struct pmbus_driver_info mp5998_info = { };static const struct i2c_device_id mp5990_id[] = { - {"mp5990" , mp5990}, - {"mp5998" , mp5998}, + { .name ="mp5990" , .driver_data = mp5990 }, + { .name ="mp5998" , .driver_data = mp5998 }, { } };MODULE_DEVICE_TABLE (i2c, mp5990_id);
drivers/hwmon/pmbus/mp9941.c +1 -1
@@ -291,7 +291,7 @@ static int mp9941_probe(struct i2c_client *client) }static const struct i2c_device_id mp9941_id[] = { - {"mp9941" }, + { .name ="mp9941" }, { } };MODULE_DEVICE_TABLE (i2c, mp9941_id);
drivers/hwmon/pmbus/mp9945.c +2 -2
@@ -215,8 +215,8 @@ static int mp9945_probe(struct i2c_client *client) }static const struct i2c_device_id mp9945_id[] = { - {"mp9945" }, - {} + { .name ="mp9945" }, + { } };MODULE_DEVICE_TABLE (i2c, mp9945_id);
drivers/hwmon/pmbus/mpq7932.c +3 -3
@@ -145,9 +145,9 @@ static const struct of_device_id mpq7932_of_match[] = {MODULE_DEVICE_TABLE (of, mpq7932_of_match);static const struct i2c_device_id mpq7932_id[] = { - {"mpq2286" , }, - {"mpq7932" , }, - { }, + { .name ="mpq2286" }, + { .name ="mpq7932" }, + { } };MODULE_DEVICE_TABLE (i2c, mpq7932_id);
drivers/hwmon/pmbus/mpq8785.c +5 -5
@@ -110,11 +110,11 @@ static struct pmbus_driver_info mpq8785_info = { };static const struct i2c_device_id mpq8785_id[] = { - {"mpm3695" , mpm3695 }, - {"mpm3695-25" , mpm3695_25 }, - {"mpm82504" , mpm82504 }, - {"mpq8785" , mpq8785 }, - { }, + { .name ="mpm3695" , .driver_data = mpm3695 }, + { .name ="mpm3695-25" , .driver_data = mpm3695_25 }, + { .name ="mpm82504" , .driver_data = mpm82504 }, + { .name ="mpq8785" , .driver_data = mpq8785 }, + { } };MODULE_DEVICE_TABLE (i2c, mpq8785_id);
drivers/hwmon/pmbus/pim4328.c +9 -9
@@ -39,15 +39,15 @@ struct pim4328_data {#define PIM4328_MFR_READ_STATUS 0xd0static const struct i2c_device_id pim4328_id[] = { - {"bmr455" , pim4328}, - {"pim4006" , pim4006}, - {"pim4106" , pim4006}, - {"pim4206" , pim4006}, - {"pim4306" , pim4006}, - {"pim4328" , pim4328}, - {"pim4406" , pim4006}, - {"pim4820" , pim4820}, - {} + { .name ="bmr455" , .driver_data = pim4328 }, + { .name ="pim4006" , .driver_data = pim4006 }, + { .name ="pim4106" , .driver_data = pim4006 }, + { .name ="pim4206" , .driver_data = pim4006 }, + { .name ="pim4306" , .driver_data = pim4006 }, + { .name ="pim4328" , .driver_data = pim4328 }, + { .name ="pim4406" , .driver_data = pim4006 }, + { .name ="pim4820" , .driver_data = pim4820 }, + { } };MODULE_DEVICE_TABLE (i2c, pim4328_id);
drivers/hwmon/pmbus/pli1209bc.c +2 -2
@@ -117,8 +117,8 @@ static int pli1209bc_probe(struct i2c_client *client) }static const struct i2c_device_id pli1209bc_id[] = { - {"pli1209bc" }, - {} + { .name ="pli1209bc" }, + { } };MODULE_DEVICE_TABLE (i2c, pli1209bc_id);
drivers/hwmon/pmbus/pm6764tr.c +2 -2
@@ -48,8 +48,8 @@ static int pm6764tr_probe(struct i2c_client *client) }static const struct i2c_device_id pm6764tr_id[] = { - {"pm6764tr" }, - {} + { .name ="pm6764tr" }, + { } };MODULE_DEVICE_TABLE (i2c, pm6764tr_id);
drivers/hwmon/pmbus/pmbus.c +30 -30
66 lines not on this page · raw message
drivers/hwmon/pmbus/pxe1610.c +4 -4
@@ -130,10 +130,10 @@ static int pxe1610_probe(struct i2c_client *client) }static const struct i2c_device_id pxe1610_id[] = { - {"pxe1610" }, - {"pxe1110" }, - {"pxm1310" }, - {} + { .name ="pxe1610" }, + { .name ="pxe1110" }, + { .name ="pxm1310" }, + { } };MODULE_DEVICE_TABLE (i2c, pxe1610_id);
drivers/hwmon/pmbus/q54sj108a2.c +4 -4
@@ -270,10 +270,10 @@ static const struct file_operations q54sj108a2_fops = { };static const struct i2c_device_id q54sj108a2_id[] = { - {"q54sj108a2" , q54sj108a2 }, - {"q54sn120a1" , q54sj108a2 }, - {"q54sw120a7" , q54sj108a2 }, - { }, + { .name ="q54sj108a2" , .driver_data = q54sj108a2 }, + { .name ="q54sn120a1" , .driver_data = q54sj108a2 }, + { .name ="q54sw120a7" , .driver_data = q54sj108a2 }, + { } };MODULE_DEVICE_TABLE (i2c, q54sj108a2_id);
drivers/hwmon/pmbus/stef48h28.c +2 -2
@@ -48,8 +48,8 @@ static int stef48h28_probe(struct i2c_client *client) }static const struct i2c_device_id stef48h28_id[] = { - {"stef48h28" }, - {} + { .name ="stef48h28" }, + { } };MODULE_DEVICE_TABLE (i2c, stef48h28_id);
drivers/hwmon/pmbus/stpddc60.c +3 -3
@@ -18,9 +18,9 @@#define STPDDC60_MFR_UV_LIMIT_OFFSET 0xe6static const struct i2c_device_id stpddc60_id[] = { - {"stpddc60" }, - {"bmr481" }, - {} + { .name ="stpddc60" }, + { .name ="bmr481" }, + { } };MODULE_DEVICE_TABLE (i2c, stpddc60_id);
drivers/hwmon/pmbus/tda38640.c +2 -2
@@ -195,8 +195,8 @@ static int tda38640_probe(struct i2c_client *client) }static const struct i2c_device_id tda38640_id[] = { - {"tda38640" }, - {} + { .name ="tda38640" }, + { } };MODULE_DEVICE_TABLE (i2c, tda38640_id);
drivers/hwmon/pmbus/tps25990.c +2 -2
@@ -387,8 +387,8 @@ static const struct pmbus_driver_info tps25990_base_info = { };static const struct i2c_device_id tps25990_i2c_id[] = { - {"tps25990" }, - {} + { .name ="tps25990" }, + { } };MODULE_DEVICE_TABLE (i2c, tps25990_i2c_id);
drivers/hwmon/pmbus/tps40422.c +2 -2
@@ -31,8 +31,8 @@ static int tps40422_probe(struct i2c_client *client) }static const struct i2c_device_id tps40422_id[] = { - {"tps40422" }, - {} + { .name ="tps40422" }, + { } };MODULE_DEVICE_TABLE (i2c, tps40422_id);
drivers/hwmon/pmbus/tps53679.c +9 -9
@@ -291,15 +291,15 @@ static int tps53679_probe(struct i2c_client *client) }static const struct i2c_device_id tps53679_id[] = { - {"bmr474" , tps53676}, - {"tps53647" , tps53647}, - {"tps53667" , tps53667}, - {"tps53676" , tps53676}, - {"tps53679" , tps53679}, - {"tps53681" , tps53681}, - {"tps53685" , tps53685}, - {"tps53688" , tps53688}, - {} + { .name ="bmr474" , .driver_data = tps53676 }, + { .name ="tps53647" , .driver_data = tps53647 }, + { .name ="tps53667" , .driver_data = tps53667 }, + { .name ="tps53676" , .driver_data = tps53676 }, + { .name ="tps53679" , .driver_data = tps53679 }, + { .name ="tps53681" , .driver_data = tps53681 }, + { .name ="tps53685" , .driver_data = tps53685 }, + { .name ="tps53688" , .driver_data = tps53688 }, + { } };MODULE_DEVICE_TABLE (i2c, tps53679_id);
drivers/hwmon/pmbus/tps546d24.c +2 -2
@@ -42,8 +42,8 @@ static int tps546d24_probe(struct i2c_client *client) }static const struct i2c_device_id tps546d24_id[] = { - {"tps546d24" }, - {} + { .name ="tps546d24" }, + { } };MODULE_DEVICE_TABLE (i2c, tps546d24_id);
drivers/hwmon/pmbus/ucd9000.c +8 -8
@@ -143,14 +143,14 @@ static int ucd9000_read_byte_data(struct i2c_client *client, int page, int reg) }static const struct i2c_device_id ucd9000_id[] = { - {"ucd9000" , ucd9000}, - {"ucd90120" , ucd90120}, - {"ucd90124" , ucd90124}, - {"ucd90160" , ucd90160}, - {"ucd90320" , ucd90320}, - {"ucd9090" , ucd9090}, - {"ucd90910" , ucd90910}, - {} + { .name ="ucd9000" , .driver_data = ucd9000 }, + { .name ="ucd90120" , .driver_data = ucd90120 }, + { .name ="ucd90124" , .driver_data = ucd90124 }, + { .name ="ucd90160" , .driver_data = ucd90160 }, + { .name ="ucd90320" , .driver_data = ucd90320 }, + { .name ="ucd9090" , .driver_data = ucd9090 }, + { .name ="ucd90910" , .driver_data = ucd90910 }, + { } };MODULE_DEVICE_TABLE (i2c, ucd9000_id);
drivers/hwmon/pmbus/ucd9200.c +9 -9
@@ -22,15 +22,15 @@ enum chips { ucd9200, ucd9220, ucd9222, ucd9224, ucd9240, ucd9244, ucd9246, ucd9248 };static const struct i2c_device_id ucd9200_id[] = { - {"ucd9200" , ucd9200}, - {"ucd9220" , ucd9220}, - {"ucd9222" , ucd9222}, - {"ucd9224" , ucd9224}, - {"ucd9240" , ucd9240}, - {"ucd9244" , ucd9244}, - {"ucd9246" , ucd9246}, - {"ucd9248" , ucd9248}, - {} + { .name ="ucd9200" , .driver_data = ucd9200 }, + { .name ="ucd9220" , .driver_data = ucd9220 }, + { .name ="ucd9222" , .driver_data = ucd9222 }, + { .name ="ucd9224" , .driver_data = ucd9224 }, + { .name ="ucd9240" , .driver_data = ucd9240 }, + { .name ="ucd9244" , .driver_data = ucd9244 }, + { .name ="ucd9246" , .driver_data = ucd9246 }, + { .name ="ucd9248" , .driver_data = ucd9248 }, + { } };MODULE_DEVICE_TABLE (i2c, ucd9200_id);
drivers/hwmon/pmbus/xdp710.c +1 -1
@@ -110,7 +110,7 @@ static const struct of_device_id xdp710_of_match[] = { };static const struct i2c_device_id xdp710_id[] = { - {"xdp710" }, + { .name ="xdp710" }, { } };MODULE_DEVICE_TABLE (i2c, xdp710_id);
drivers/hwmon/pmbus/xdp720.c +2 -2
@@ -106,8 +106,8 @@ static const struct of_device_id xdp720_of_match[] = {MODULE_DEVICE_TABLE (of, xdp720_of_match);static const struct i2c_device_id xdp720_id[] = { - {"xdp720" }, - {} + { .name ="xdp720" }, + { } };MODULE_DEVICE_TABLE (i2c, xdp720_id);
drivers/hwmon/pmbus/xdpe12284.c +4 -4
@@ -164,10 +164,10 @@ static int xdpe122_probe(struct i2c_client *client) }static const struct i2c_device_id xdpe122_id[] = { - {"xdpe11280" }, - {"xdpe12254" }, - {"xdpe12284" }, - {} + { .name ="xdpe11280" }, + { .name ="xdpe12254" }, + { .name ="xdpe12284" }, + { } };MODULE_DEVICE_TABLE (i2c, xdpe122_id);
drivers/hwmon/pmbus/xdpe152c4.c +3 -3
@@ -44,9 +44,9 @@ static int xdpe152_probe(struct i2c_client *client) }static const struct i2c_device_id xdpe152_id[] = { - {"xdpe152c4" }, - {"xdpe15284" }, - {} + { .name ="xdpe152c4" }, + { .name ="xdpe15284" }, + { } };MODULE_DEVICE_TABLE (i2c, xdpe152_id);
drivers/hwmon/pmbus/xdpe1a2g7b.c +3 -3
@@ -87,9 +87,9 @@ static int xdpe1a2g7b_probe(struct i2c_client *client) }static const struct i2c_device_id xdpe1a2g7b_id[] = { - {"xdpe1a2g5b" }, - {"xdpe1a2g7b" }, - {} + { .name ="xdpe1a2g5b" }, + { .name ="xdpe1a2g7b" }, + { } };MODULE_DEVICE_TABLE (i2c, xdpe1a2g7b_id);
drivers/hwmon/pmbus/zl6100.c +22 -22
50 lines not on this page · raw message
drivers/hwmon/powr1220.c +2 -2
@@ -306,8 +306,8 @@ static int powr1220_probe(struct i2c_client *client) }static const struct i2c_device_id powr1220_ids[] = { - {"powr1014" , powr1014, }, - {"powr1220" , powr1220, }, + { .name ="powr1014" , .driver_data = powr1014 }, + { .name ="powr1220" , .driver_data = powr1220 }, { } };
drivers/hwmon/pt5161l.c +2 -2
@@ -617,8 +617,8 @@ static const struct acpi_device_id __maybe_unused pt5161l_acpi_match[] = {MODULE_DEVICE_TABLE (acpi, pt5161l_acpi_match);static const struct i2c_device_id pt5161l_id[] = { - {"pt5161l" }, - {} + { .name ="pt5161l" }, + { } };MODULE_DEVICE_TABLE (i2c, pt5161l_id);
drivers/hwmon/sbtsi_temp.c +2 -2
@@ -221,8 +221,8 @@ static int sbtsi_probe(struct i2c_client *client) }static const struct i2c_device_id sbtsi_id[] = { - {"sbtsi" }, - {} + { .name ="sbtsi" }, + { } };MODULE_DEVICE_TABLE (i2c, sbtsi_id);
drivers/hwmon/sg2042-mcu.c +1 -1
@@ -333,7 +333,7 @@ static int sg2042_mcu_i2c_probe(struct i2c_client *client) }static const struct i2c_device_id sg2042_mcu_id[] = { - {"sg2042-hwmon-mcu" }, + { .name ="sg2042-hwmon-mcu" }, { } };MODULE_DEVICE_TABLE (i2c, sg2042_mcu_id);
drivers/hwmon/sht21.c +3 -3
@@ -275,9 +275,9 @@ static int sht21_probe(struct i2c_client *client)/* Device ID table */ static const struct i2c_device_id sht21_id[] = { - {"sht20" }, - {"sht21" }, - {"sht25" }, + { .name ="sht20" }, + { .name ="sht21" }, + { .name ="sht25" }, { } };MODULE_DEVICE_TABLE (i2c, sht21_id);
drivers/hwmon/sht3x.c +4 -4
@@ -931,10 +931,10 @@ static int sht3x_probe(struct i2c_client *client)/* device ID table */ static const struct i2c_device_id sht3x_ids[] = { - {"sht3x" , sht3x}, - {"sts3x" , sts3x}, - {"sht85" , sht3x}, - {} + { .name ="sht3x" , .driver_data = sht3x }, + { .name ="sts3x" , .driver_data = sts3x }, + { .name ="sht85" , .driver_data = sht3x }, + { } };MODULE_DEVICE_TABLE (i2c, sht3x_ids);
drivers/hwmon/sht4x.c +2 -2
@@ -424,8 +424,8 @@ static int sht4x_probe(struct i2c_client *client) }static const struct i2c_device_id sht4x_id[] = { - {"sht4x" }, - { }, + { .name ="sht4x" }, + { } };MODULE_DEVICE_TABLE (i2c, sht4x_id);
drivers/hwmon/shtc1.c +3 -3
@@ -257,9 +257,9 @@ static int shtc1_probe(struct i2c_client *client)/* device ID table */ static const struct i2c_device_id shtc1_id[] = { - {"shtc1" , shtc1 }, - {"shtw1" , shtc1 }, - {"shtc3" , shtc3 }, + { .name ="shtc1" , .driver_data = shtc1 }, + { .name ="shtw1" , .driver_data = shtc1 }, + { .name ="shtc3" , .driver_data = shtc3 }, { } };MODULE_DEVICE_TABLE (i2c, shtc1_id);
drivers/hwmon/smsc47m192.c +1 -1
@@ -618,7 +618,7 @@ static int smsc47m192_probe(struct i2c_client *client) }static const struct i2c_device_id smsc47m192_id[] = { - {"smsc47m192" }, + { .name ="smsc47m192" }, { } };MODULE_DEVICE_TABLE (i2c, smsc47m192_id);
drivers/hwmon/spd5118.c +1 -1
@@ -746,7 +746,7 @@ static int spd5118_i2c_probe(struct i2c_client *client) }static const struct i2c_device_id spd5118_i2c_id[] = { - {"spd5118" }, + { .name ="spd5118" }, { } };MODULE_DEVICE_TABLE (i2c, spd5118_i2c_id);
drivers/hwmon/stts751.c +1 -1
@@ -72,7 +72,7 @@ static const int stts751_intervals[] = { };static const struct i2c_device_id stts751_id[] = { - {"stts751" }, + { .name ="stts751" }, { } };
drivers/hwmon/tc654.c +3 -3
@@ -550,9 +550,9 @@ static int tc654_probe(struct i2c_client *client) }static const struct i2c_device_id tc654_id[] = { - {"tc654" }, - {"tc655" }, - {} + { .name ="tc654" }, + { .name ="tc655" }, + { } };MODULE_DEVICE_TABLE (i2c, tc654_id);
drivers/hwmon/tc74.c +2 -2
@@ -151,8 +151,8 @@ static int tc74_probe(struct i2c_client *client) }static const struct i2c_device_id tc74_id[] = { - {"tc74" }, - {} + { .name ="tc74" }, + { } };MODULE_DEVICE_TABLE (i2c, tc74_id);
drivers/hwmon/thmc50.c +2 -2
@@ -407,8 +407,8 @@ static int thmc50_probe(struct i2c_client *client) }static const struct i2c_device_id thmc50_id[] = { - {"adm1022" , adm1022 }, - {"thmc50" , thmc50 }, + { .name ="adm1022" , .driver_data = adm1022 }, + { .name ="thmc50" , .driver_data = thmc50 }, { } };MODULE_DEVICE_TABLE (i2c, thmc50_id);
drivers/hwmon/tmp102.c +1 -1
@@ -395,7 +395,7 @@ static int tmp102_resume(struct device *dev) static DEFINE_SIMPLE_DEV_PM_OPS(tmp102_dev_pm_ops, tmp102_suspend, tmp102_resume);static const struct i2c_device_id tmp102_id[] = { - {"tmp102" }, + { .name ="tmp102" }, { } };MODULE_DEVICE_TABLE (i2c, tmp102_id);
drivers/hwmon/tmp103.c +1 -1
@@ -194,7 +194,7 @@ static int tmp103_resume(struct device *dev) static DEFINE_SIMPLE_DEV_PM_OPS(tmp103_dev_pm_ops, tmp103_suspend, tmp103_resume);static const struct i2c_device_id tmp103_id[] = { - {"tmp103" }, + { .name ="tmp103" }, { } };MODULE_DEVICE_TABLE (i2c, tmp103_id);
drivers/hwmon/tmp108.c +4 -4
@@ -537,10 +537,10 @@ static int tmp108_resume(struct device *dev) static DEFINE_SIMPLE_DEV_PM_OPS(tmp108_dev_pm_ops, tmp108_suspend, tmp108_resume);static const struct i2c_device_id tmp108_i2c_ids[] = { - {"p3t1035" , (unsigned long )&p3t1035_data }, - {"p3t1085" , (unsigned long )&tmp108_data }, - {"tmp108" , (unsigned long )&tmp108_data }, - {} + { .name ="p3t1035" , .driver_data = (unsigned long )&p3t1035_data }, + { .name ="p3t1085" , .driver_data = (unsigned long )&tmp108_data }, + { .name ="tmp108" , .driver_data = (unsigned long )&tmp108_data }, + { } };MODULE_DEVICE_TABLE (i2c, tmp108_i2c_ids);
drivers/hwmon/tmp401.c +5 -5
@@ -90,11 +90,11 @@ static const u8 TMP432_STATUS_REG[] = {*/ static const struct i2c_device_id tmp401_id[] = { - {"tmp401" , tmp401 }, - {"tmp411" , tmp411 }, - {"tmp431" , tmp431 }, - {"tmp432" , tmp432 }, - {"tmp435" , tmp435 }, + { .name ="tmp401" , .driver_data = tmp401 }, + { .name ="tmp411" , .driver_data = tmp411 }, + { .name ="tmp431" , .driver_data = tmp431 }, + { .name ="tmp432" , .driver_data = tmp432 }, + { .name ="tmp435" , .driver_data = tmp435 }, { } };MODULE_DEVICE_TABLE (i2c, tmp401_id);
drivers/hwmon/tmp421.c +5 -5
@@ -56,11 +56,11 @@ static const u8 TMP421_TEMP_LSB[MAX_CHANNELS] = { 0x10, 0x11, 0x12, 0x13 };#define TMP442_DEVICE_ID 0x42static const struct i2c_device_id tmp421_id[] = { - {"tmp421" ,2 }, - {"tmp422" ,3 }, - {"tmp423" ,4 }, - {"tmp441" ,2 }, - {"tmp442" ,3 }, + { .name ="tmp421" , .driver_data =2 }, + { .name ="tmp422" , .driver_data =3 }, + { .name ="tmp423" , .driver_data =4 }, + { .name ="tmp441" , .driver_data =2 }, + { .name ="tmp442" , .driver_data =3 }, { } };MODULE_DEVICE_TABLE (i2c, tmp421_id);
drivers/hwmon/tmp464.c +2 -2
@@ -65,8 +65,8 @@ static const u8 TMP464_THERM2_LIMIT[MAX_CHANNELS] = {#define TMP468_DEVICE_ID 0x0468static const struct i2c_device_id tmp464_id[] = { - {"tmp464" ,TMP464_NUM_CHANNELS }, - {"tmp468" ,TMP468_NUM_CHANNELS }, + { .name ="tmp464" , .driver_data =TMP464_NUM_CHANNELS }, + { .name ="tmp468" , .driver_data =TMP468_NUM_CHANNELS }, { } };MODULE_DEVICE_TABLE (i2c, tmp464_id);
drivers/hwmon/tmp513.c +2 -2
@@ -611,8 +611,8 @@ static int tmp51x_init(struct tmp51x_data *data) }static const struct i2c_device_id tmp51x_id[] = { - {"tmp512" ,TMP512_MAX_CHANNELS }, - {"tmp513" ,TMP513_MAX_CHANNELS }, + { .name ="tmp512" , .driver_data =TMP512_MAX_CHANNELS }, + { .name ="tmp513" , .driver_data =TMP513_MAX_CHANNELS }, { } };MODULE_DEVICE_TABLE (i2c, tmp51x_id);
drivers/hwmon/w83773g.c +1 -1
@@ -34,7 +34,7 @@ static const u8 W83773_OFFSET_MSB[2] = { 0x11, 0x15 };/* this is the number of sensors in the device */ static const struct i2c_device_id w83773_id[] = { - {"w83773g" }, + { .name ="w83773g" }, { } };
drivers/hwmon/w83781d.c +4 -4
@@ -1559,10 +1559,10 @@ static struct w83781d_data *w83781d_update_device(struct device *dev) }static const struct i2c_device_id w83781d_ids[] = { - {"w83781d" , w83781d, }, - {"w83782d" , w83782d, }, - {"w83783s" , w83783s, }, - {"as99127f" , as99127f }, + { .name ="w83781d" , .driver_data = w83781d }, + { .name ="w83782d" , .driver_data = w83782d }, + { .name ="w83783s" , .driver_data = w83783s }, + { .name ="as99127f" , .driver_data = as99127f }, {/* LIST END */ } };MODULE_DEVICE_TABLE (i2c, w83781d_ids);
drivers/hwmon/w83791d.c +1 -1
@@ -333,7 +333,7 @@ static void w83791d_print_debug(struct w83791d_data *data, struct device *dev);static void w83791d_init_client (struct i2c_client *client);static const struct i2c_device_id w83791d_id[] = { - {"w83791d" }, + { .name ="w83791d" }, { } };MODULE_DEVICE_TABLE (i2c, w83791d_id);
drivers/hwmon/w83792d.c +1 -1
@@ -296,7 +296,7 @@ static void w83792d_print_debug(struct w83792d_data *data, struct device *dev);static void w83792d_init_client (struct i2c_client *client);static const struct i2c_device_id w83792d_id[] = { - {"w83792d" }, + { .name ="w83792d" }, { } };MODULE_DEVICE_TABLE (i2c, w83792d_id);
drivers/hwmon/w83793.c +1 -1
@@ -291,7 +291,7 @@ static void w83793_update_nonvolatile(struct device *dev);static struct w83793_data *w83793_update_device (struct device *dev);static const struct i2c_device_id w83793_id[] = { - {"w83793" }, + { .name ="w83793" }, { } };MODULE_DEVICE_TABLE (i2c, w83793_id);
drivers/hwmon/w83795.c +2 -2
@@ -2243,8 +2243,8 @@ static void w83795_remove(struct i2c_client *client)static const struct i2c_device_id w83795_id[] = { - {"w83795g" , w83795g }, - {"w83795adg" , w83795adg }, + { .name ="w83795g" , .driver_data = w83795g }, + { .name ="w83795adg" , .driver_data = w83795adg }, { } };MODULE_DEVICE_TABLE (i2c, w83795_id);
drivers/hwmon/w83l785ts.c +1 -1
@@ -74,7 +74,7 @@ static struct w83l785ts_data *w83l785ts_update_device(struct device *dev);*/ static const struct i2c_device_id w83l785ts_id[] = { - {"w83l785ts" }, + { .name ="w83l785ts" }, { } };MODULE_DEVICE_TABLE (i2c, w83l785ts_id);
drivers/hwmon/w83l786ng.c +1 -1
@@ -751,7 +751,7 @@ w83l786ng_probe(struct i2c_client *client) }static const struct i2c_device_id w83l786ng_id[] = { - {"w83l786ng" }, + { .name ="w83l786ng" }, { } };MODULE_DEVICE_TABLE (i2c, w83l786ng_id);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 215/744 hwmon: (pmbus/max34440): add support adpm12250
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexis Czezar Torreno <[email protected]>
[ Upstream commit 479bfeba2eb62666cd4b981c8e721c61dcf36e7d ]
ADPM12250 is a quarter brick DC/DC Power Module. It is a high power non-isolated converter capable of delivering regulated 12V with continuous power level of 2500W. Uses PMBus.
Stable-dep-of: af01dab0c39a ("hwmon: (pmbus/max34440) block unsupported VIN and IIN limit registers")
--- Documentation/hwmon/max34440.rst | 27 ++++++++++++------- drivers/hwmon/pmbus/max34440.c | 45 +++++++++++++++++++++++++++++--- 2 files changed, 60 insertions(+), 12 deletions(-)
Documentation/hwmon/max34440.rst +18 -9
@@ -19,6 +19,14 @@ Supported chips: Datasheet: - + * ADI ADPM12250 + + Prefixes: 'adpm12250' + + Addresses scanned: - + + Datasheet: - + * Maxim MAX34440 Prefixes: 'max34440'
@@ -87,11 +95,11 @@ This driver supports multiple devices: hardware monitoring for Maxim MAX34440 PMBus 6-Channel Power-Supply Manager, MAX34441 PMBus 5-Channel Power-Supply Manager and Intelligent Fan Controller, and MAX34446 PMBus Power-Supply Data Logger; PMBus Voltage Monitor and Sequencers for MAX34451, MAX34460, and -MAX34461; PMBus DC/DC Power Module ADPM12160, and ADPM12200. The MAX34451 -supports monitoring voltage or current of 12 channels based on GIN pins. The -MAX34460 supports 12 voltage channels, and the MAX34461 supports 16 voltage -channels. The ADPM12160, and ADPM12200 also monitors both input and output -of voltage and current. +MAX34461; PMBus DC/DC Power Module ADPM12160, ADPM12200, and ADPM12250. The +MAX34451 supports monitoring voltage or current of 12 channels based on GIN +pins. The MAX34460 supports 12 voltage channels, and the MAX34461 supports 16 +voltage channels. The ADPM12160, ADPM12200, and ADPM12250 also monitors both +input and output of voltage and current. The driver is a client driver to the core PMBus driver. Please see Documentation/hwmon/pmbus.rst for details on PMBus client drivers.
@@ -149,7 +157,7 @@ in[1-6]_reset_history Write any value to reset history. .. note:: - MAX34446 only supports in[1-4]. - - ADPM12160, and ADPM12200 only supports in[1-2]. Label is "vin1" + - ADPM12160, ADPM12200, and ADPM12250 only supports in[1-2]. Label is "vin1" and "vout1" respectively. Curr
@@ -172,8 +180,9 @@ curr[1-6]_reset_history Write any value to reset history. - in6 and curr6 attributes only exist for MAX34440. - MAX34446 only supports curr[1-4]. - - For ADPM12160, and ADPM12200, curr[1] is "iin1" and curr[2-6] - are "iout[1-5]". + - For ADPM12160, ADPM12200, and ADPM12250, curr[1] is "iin1" + - For ADPM12160, and ADPM12200 curr[2-6] are "iout[1-5]". + - For ADPM12250, curr[2-4] are "iout[1-3]". Power ~~~~~
@@ -209,7 +218,7 @@ temp[1-8]_reset_history Write any value to reset history. .. note:: - temp7 and temp8 attributes only exist for MAX34440. - MAX34446 only supports temp[1-3]. - - ADPM12160, and ADPM12200 only supports temp[1]. + - ADPM12160, ADPM12200, and ADPM12250 only supports temp[1]. .. note::
drivers/hwmon/pmbus/max34440.c +42 -3
81 lines not on this page · raw message
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 216/744 hwmon: (pmbus/max34440) block unsupported VIN and IIN limit registers
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexis Czezar Torreno <[email protected]>
[ Upstream commit af01dab0c39a7aefc47a109201e4134ea6bd3005 ]
MAX34451 and ADPM chips do not support standard PMBus VIN/IIN limit registers, manufacturer specific min/max registers, or undercurrent or undertemperature fault limits. STATUS_BYTE and STATUS_OTHER are also not available. Accessing these non-existent registers during driver initialization triggers a CML error and asserts ALERT. Handled by blocking these functions during read/write.
--- drivers/hwmon/pmbus/max34440.c | 80 ++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+)
drivers/hwmon/pmbus/max34440.c +80 -0
@@ -88,6 +88,33 @@ static int max34440_read_word_data(struct i2c_client *client, int page, ret =pmbus_read_word_data (client, page, phase, data->iout_oc_warn_limit);break ; +case PMBUS_VIN_OV_FAULT_LIMIT : +case PMBUS_VIN_OV_WARN_LIMIT : +case PMBUS_VIN_UV_WARN_LIMIT : +case PMBUS_VIN_UV_FAULT_LIMIT : +case PMBUS_MFR_VIN_MIN : +case PMBUS_MFR_VIN_MAX : +case PMBUS_IIN_OC_WARN_LIMIT : +case PMBUS_IIN_OC_FAULT_LIMIT : +case PMBUS_MFR_IIN_MAX : +case PMBUS_MFR_VOUT_MIN : +case PMBUS_MFR_VOUT_MAX : +case PMBUS_IOUT_UC_FAULT_LIMIT : +case PMBUS_MFR_IOUT_MAX : +case PMBUS_UT_WARN_LIMIT : +case PMBUS_UT_FAULT_LIMIT : +case PMBUS_MFR_MAX_TEMP_1 : +/* +* MAX34451/ADPM family do not support VIN/IIN limit registers, +* manufacturer-specific min/max registers, or undercurrent/ +* undertemperature fault limits. Accessing these triggers CML +* error and asserts ALERT. +*/ +if (data->id == max34451 || data->id == adpm12160 || + data->id == adpm12200 || data->id == adpm12250) +return -ENXIO ; + ret = -ENODATA ; +break ;case PMBUS_VIRT_READ_VOUT_MIN : ret =pmbus_read_word_data (client, page, phase,MAX34440_MFR_VOUT_MIN );
@@ -244,6 +271,51 @@ static int max34440_read_byte_data(struct i2c_client *client, int page, int reg)return ret; } +static int max34451_read_byte_data (struct i2c_client *client,int page,int reg) +{ +const struct pmbus_driver_info *info =pmbus_get_driver_info (client); +const struct max34440_data *data =to_max34440_data (info); + +switch (reg) { +case PMBUS_STATUS_BYTE : +case PMBUS_STATUS_OTHER : +/* +* MAX34451/ADPM family do not support STATUS_BYTE or +* STATUS_OTHER registers. Accessing them triggers CML +* error and asserts ALERT. +*/ +if (data->id == max34451 || data->id == adpm12160 || + data->id == adpm12200 || data->id == adpm12250) +return -ENXIO ; +return -ENODATA ; +default : +return -ENODATA ; + } +} + +static int max34451_write_byte_data (struct i2c_client *client,int page, +int reg,u8 byte) +{ +const struct pmbus_driver_info *info =pmbus_get_driver_info (client); +const struct max34440_data *data =to_max34440_data (info); + +switch (reg) { +case PMBUS_STATUS_BYTE : +case PMBUS_STATUS_OTHER : +/* +* MAX34451/ADPM family do not support STATUS_BYTE or +* STATUS_OTHER registers. Writing to them triggers CML +* error and asserts ALERT. +*/ +if (data->id == max34451 || data->id == adpm12160 || + data->id == adpm12200 || data->id == adpm12250) +return -ENXIO ; +return -ENODATA ; +default : +return -ENODATA ; + } +} +static int max34451_set_supported_funcs (struct i2c_client *client,struct max34440_data *data) {
@@ -363,7 +435,9 @@ static struct pmbus_driver_info max34440_info[] = { .func[9] = PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT, .func[10] = PMBUS_HAVE_IIN | PMBUS_HAVE_STATUS_INPUT, .func[18] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, + .read_byte_data = max34451_read_byte_data, .read_word_data = max34440_read_word_data, + .write_byte_data = max34451_write_byte_data, .write_word_data = max34440_write_word_data, }, [adpm12200] = {
@@ -399,7 +473,9 @@ static struct pmbus_driver_info max34440_info[] = { .func[10] = PMBUS_HAVE_IIN | PMBUS_HAVE_STATUS_INPUT, .func[14] = PMBUS_HAVE_IOUT, .func[18] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, + .read_byte_data = max34451_read_byte_data, .read_word_data = max34440_read_word_data, + .write_byte_data = max34451_write_byte_data, .write_word_data = max34440_write_word_data, }, [adpm12250] = {
@@ -433,7 +509,9 @@ static struct pmbus_driver_info max34440_info[] = { .func[10] = PMBUS_HAVE_IIN | PMBUS_HAVE_STATUS_INPUT, .func[14] = PMBUS_HAVE_IOUT, .func[18] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, + .read_byte_data = max34451_read_byte_data, .read_word_data = max34440_read_word_data, + .write_byte_data = max34451_write_byte_data, .write_word_data = max34440_write_word_data, }, [max34440] = {
@@ -581,7 +659,9 @@ static struct pmbus_driver_info max34440_info[] = { .func[18] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, .func[19] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, .func[20] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, + .read_byte_data = max34451_read_byte_data, .read_word_data = max34440_read_word_data, + .write_byte_data = max34451_write_byte_data, .write_word_data = max34440_write_word_data, .page_change_delay = MAX34440_PAGE_CHANGE_DELAY, },
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 217/744 hwmon: (asus-ec-sensors) fix looping over banks while reading from EC
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eugene Shalygin <[email protected]>
[ Upstream commit e741d13cc2abfc6fccebe2008057aa52e285223e ]
Do not assume there are only bank 0 and bank 1 available, just use '!=' for bank comparison.
--- drivers/hwmon/asus-ec-sensors.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/hwmon/asus-ec-sensors.c +1 -1
@@ -1154,7 +1154,7 @@ static int asus_ec_block_read(const struct device *dev, }for (ireg =0 ; ireg < ec->nr_registers; ireg++) { reg_bank =register_bank (ec->registers[ireg]); -if (reg_bank < bank) { +if (reg_bank != bank) {continue ; } ec_read(register_index(ec->registers[ireg]),
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 218/744 hwmon: (asus-ec-sensors) fix EC read intervals
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eugene Shalygin <[email protected]>
[ Upstream commit 60710b2af13b81da71b429d3f8b19dd70310729d ]
Take INITIAL_JIFFIES into account when setting up next update time.
--- drivers/hwmon/asus-ec-sensors.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/hwmon/asus-ec-sensors.c +4 -4
@@ -974,7 +974,7 @@ struct ec_sensors_data {/* sorted list of unique register banks */ u8 banks[ASUS_EC_MAX_BANK +1 ];/* in jiffies */ -unsigned long last_updated; +u64 next_update;struct lock_data lock_data;/* number of board EC sensors */ u8 nr_sensors;
@@ -1243,13 +1243,12 @@ static int get_cached_value_or_update(const struct device *dev,int sensor_index, struct ec_sensors_data *state, s32 *value) { - if (time_after(jiffies, state->last_updated + HZ)) { + if (time_after64(get_jiffies_64(), state->next_update)) { if (update_ec_sensors(dev, state)) { dev_err(dev, "update_ec_sensors() failure\n");return -EIO ; } - - state->last_updated = jiffies; + state->next_update =get_jiffies_64 () +HZ ; } *value = state->sensors[sensor_index].cached_value;
@@ -1367,6 +1366,7 @@ static int asus_ec_probe(struct platform_device *pdev)if (!ec_data)return -ENOMEM ; + ec_data->next_update =INITIAL_JIFFIES ;dev_set_drvdata (dev, ec_data); ec_data->board_info = pboard_info;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 219/744 hwmon: (asus-ec-sensors) add missed handle for ENOMEM
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eugene Shalygin <[email protected]>
[ Upstream commit 9813c1f49efeadbcb17e4a41972350ac783f9cac ]
Add missing return value check in the setup function.
--- drivers/hwmon/asus-ec-sensors.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
drivers/hwmon/asus-ec-sensors.c +5 -3
@@ -1460,9 +1460,11 @@ static int asus_ec_probe(struct platform_device *pdev)if (!nr_count[type])continue ; -asus_ec_hwmon_add_chan_info (asus_ec_hwmon_chan, dev, - nr_count[type], type, - hwmon_attributes[type]); + status =asus_ec_hwmon_add_chan_info (asus_ec_hwmon_chan, dev, + nr_count[type], type, + hwmon_attributes[type]); +if (status) +return status; *ptr_asus_ec_ci++ = asus_ec_hwmon_chan++; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 220/744 smb: client: validate DFS referral PathConsumed
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yichong Chen <[email protected]>
[ Upstream commit f6f5ee2aa33b350c671721b965251c42cebb962e ]
parse_dfs_referrals() validates that the response contains the fixed referral entry array and, on for-next, the per-referral string offsets. However, the response also contains a PathConsumed value that is later used for DFS path parsing.
If a malformed response provides a PathConsumed value larger than the search name, later DFS parsing can advance beyond the end of the path.
Validate PathConsumed against the search name length before storing it in the parsed referral.
--- fs/smb/client/misc.c | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-)
fs/smb/client/misc.c +25 -9
@@ -678,6 +678,8 @@ parse_dfs_referrals(struct get_dfs_referral_rsp *rsp, u32 rsp_size,int i, rc =0 ;char *data_end;struct dfs_referral_level_3 *ref; +unsigned int path_consumed; +size_t search_name_len;if (rsp_size <sizeof (*rsp)) { cifs_dbg(VFS | ONCE,
@@ -724,6 +726,7 @@ parse_dfs_referrals(struct get_dfs_referral_rsp *rsp, u32 rsp_size, rc = -ENOMEM ; goto parse_DFS_referrals_exit; } + search_name_len =strlen (searchName);/* collect necessary data from referrals */ for (i =0 ; i < *num_of_nodes; i++) {
@@ -732,21 +735,34 @@ parse_dfs_referrals(struct get_dfs_referral_rsp *rsp, u32 rsp_size,struct dfs_info3_param *node = (*target_nodes)+i; node->flags =le32_to_cpu (rsp->DFSFlags); + path_consumed =le16_to_cpu (rsp->PathConsumed);if (is_unicode) { -__le16 *tmp =kmalloc (strlen (searchName)*2 +2 , -GFP_KERNEL ); -if (tmp ==NULL ) { +size_t search_name_utf16_len = search_name_len *2 +2 ; +__le16 *tmp; + +if (path_consumed > search_name_utf16_len) { + rc = -EINVAL ; + goto parse_DFS_referrals_exit; + } + + tmp =kmalloc (search_name_utf16_len,GFP_KERNEL ); +if (!tmp) { rc = -ENOMEM ; goto parse_DFS_referrals_exit; } -cifsConvertToUTF16 ((__le16 *) tmp, searchName, +cifsConvertToUTF16 ((__le16 *)tmp, searchName,PATH_MAX , nls_codepage, remap); - node->path_consumed =cifs_utf16_bytes (tmp, -le16_to_cpu (rsp->PathConsumed), - nls_codepage); + node->path_consumed =cifs_utf16_bytes (tmp, path_consumed, + nls_codepage);kfree (tmp); - }else - node->path_consumed =le16_to_cpu (rsp->PathConsumed); + }else { +if (path_consumed > search_name_len) { + rc = -EINVAL ; + goto parse_DFS_referrals_exit; + } + + node->path_consumed = path_consumed; + } node->server_type =le16_to_cpu (ref->ServerType); node->ref_flag =le16_to_cpu (ref->ReferralEntryFlags);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 221/744 drm/i915/backlight: Remove DP_EDP_BACKLIGHT_AUX_ENABLE_CAP check for DPCD backlight
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Suraj Kandpal <[email protected]>
[ Upstream commit a411ea4a87162898d2a0547fdfb721ddb7626be3 ]
Turns out some panels allow only AUX based backlight
by just setting the DP_EDP_BACKLIGHT_BRIGHTNESS_AUX_SET_CAP and not setting the DP_EDP_BACKLIGHT_AUX_ENABLE_CAP.
If we make DP_EDP_BACKLIGHT_AUX_ENABLE_CAP a necessity for AUX based DPCD backlight these panels loose the ability to manipulate backlight via AUX, especially ones with no PWM controller. Remove this check from function so that panels who do not advertise DP_EDP_BACKLIGHT_AUX_ENABLE_CAP but advertise DP_EDP_BACKLIGHT_BRIGHTNESS_AUX_SET_CAP are able to manipulate backlight again.
--- drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-)
drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +1 -6
@@ -615,12 +615,7 @@ check_if_vesa_backlight_possible(struct intel_dp *intel_dp)int ret;u8 bit_min, bit_max; -/* -* Since we only support Fully AUX Based VESA Backlight interface make sure -* backlight enable is possible via AUX along with backlight adjustment -*/ -if (!(intel_dp->edp_dpcd[1 ] &DP_EDP_BACKLIGHT_AUX_ENABLE_CAP && - intel_dp->edp_dpcd[2 ] &DP_EDP_BACKLIGHT_BRIGHTNESS_AUX_SET_CAP )) +if (!(intel_dp->edp_dpcd[2 ] &DP_EDP_BACKLIGHT_BRIGHTNESS_AUX_SET_CAP ))return false; ret =drm_dp_dpcd_read_byte (&intel_dp->aux,DP_EDP_PWMGEN_BIT_COUNT_CAP_MIN , &bit_min);
Signature · 1 line
2.53.0