5.8.6-rc1 review
Subsystems (6)
Greg Kroah-Hartman
maintainerPATCH 150/255 scsi: qla2xxx: Indicate correct supported speeds for Mezz card
In reply to Greg Kroah-HartmanFrom: Quinn Tran <[email protected]>
[ Upstream commit 4709272f6327cc4a8ee1dc55771bcf9718346980 ]
Correct the supported speeds for 16G Mezz card.
--- drivers/scsi/qla2xxx/qla_gs.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-)
drivers/scsi/qla2xxx/qla_gs.c +12 -5
@@ -1505,11 +1505,11 @@ qla2x00_prep_ct_fdmi_req(struct ct_sns_pkt *p, uint16_t cmd,static uint qla25xx_fdmi_port_speed_capability (struct qla_hw_data *ha) { +uint speeds =0 ; +if (IS_CNA_CAPABLE (ha))return FDMI_PORT_SPEED_10GB ;if (IS_QLA28XX (ha) ||IS_QLA27XX (ha)) { -uint speeds =0 ; -if (ha->max_supported_speed ==2 ) {if (ha->min_supported_speed <=6 ) speeds |=FDMI_PORT_SPEED_64GB ;
@@ -1536,9 +1536,16 @@ qla25xx_fdmi_port_speed_capability(struct qla_hw_data *ha) }return speeds; } -if (IS_QLA2031 (ha)) -return FDMI_PORT_SPEED_16GB |FDMI_PORT_SPEED_8GB | -FDMI_PORT_SPEED_4GB ; +if (IS_QLA2031 (ha)) { +if ((ha->pdev->subsystem_vendor ==0x103C ) && + (ha->pdev->subsystem_device ==0x8002 )) { + speeds =FDMI_PORT_SPEED_16GB ; + }else { + speeds =FDMI_PORT_SPEED_16GB |FDMI_PORT_SPEED_8GB | +FDMI_PORT_SPEED_4GB ; + } +return speeds; + }if (IS_QLA25XX (ha))return FDMI_PORT_SPEED_8GB |FDMI_PORT_SPEED_4GB |FDMI_PORT_SPEED_2GB |FDMI_PORT_SPEED_1GB ;
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 151/255 scsi: qla2xxx: Fix login timeout
In reply to Greg Kroah-HartmanFrom: Quinn Tran <[email protected]>
[ Upstream commit abb31aeaa9b20680b0620b23fea5475ea4591e31 ]
Multipath errors were seen during failback due to login timeout. The remote device sent LOGO, the local host tore down the session and did relogin. The RSCN arrived indicates remote device is going through failover after which the relogin is in a 20s timeout phase. At this point the driver is stuck in the relogin process. Add a fix to delete the session as part of abort/flush the login.
--- drivers/scsi/qla2xxx/qla_gs.c | 18 +++++++++++++++--- drivers/scsi/qla2xxx/qla_target.c | 2 +- 2 files changed, 16 insertions(+), 4 deletions(-)
drivers/scsi/qla2xxx/qla_gs.c +15 -3
@@ -3538,10 +3538,22 @@ login_logout: }if (fcport->scan_state !=QLA_FCPORT_FOUND ) { +bool do_delete = false; + +if (fcport->scan_needed && + fcport->disc_state ==DSC_LOGIN_PEND ) { +/* Cable got disconnected after we sent +* a login. Do delete to prevent timeout. +*/ + fcport->logout_on_delete =1 ; + do_delete = true; + } + fcport->scan_needed =0 ; -if ((qla_dual_mode_enabled (vha) || -qla_ini_mode_enabled (vha)) && -atomic_read (&fcport->state) ==FCS_ONLINE ) { +if (((qla_dual_mode_enabled (vha) || +qla_ini_mode_enabled (vha)) && +atomic_read (&fcport->state) ==FCS_ONLINE ) || + do_delete) {if (fcport->loop_id !=FC_NO_LOOP_ID ) {if (fcport->flags &FCF_FCP2_DEVICE ) fcport->logout_on_delete =0 ;
drivers/scsi/qla2xxx/qla_target.c +1 -1
@@ -1270,7 +1270,7 @@ void qlt_schedule_sess_for_deletion(struct fc_port *sess)qla24xx_chk_fcp_state (sess); -ql_dbg (ql_dbg_tgt, sess->vha,0xe001 , +ql_dbg (ql_dbg_disc, sess->vha,0xe001 ,"Scheduling sess %p for deletion %8phC\n" , sess, sess->port_name);
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 152/255 scsi: qla2xxx: Check if FW supports MQ before enabling
In reply to Greg Kroah-HartmanFrom: Saurav Kashyap <[email protected]>
[ Upstream commit dffa11453313a115157b19021cc2e27ea98e624c ]
OS boot during Boot from SAN was stuck at dracut emergency shell after enabling NVMe driver parameter. For non-MQ support the driver was enabling MQ. Add a check to confirm if FW supports MQ.
--- drivers/scsi/qla2xxx/qla_os.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/scsi/qla2xxx/qla_os.c +5 -0
@@ -2017,6 +2017,11 @@ skip_pio:/* Determine queue resources */ ha->max_req_queues = ha->max_rsp_queues =1 ; ha->msix_count =QLA_BASE_VECTORS ; + +/* Check if FW supports MQ or not */ +if (!(ha->fw_attributes &BIT_6 )) + goto mqiobase_exit; +if (!ql2xmqsupport || !ql2xnvmeenable || (!IS_QLA25XX (ha) && !IS_QLA81XX (ha))) goto mqiobase_exit;
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 153/255 scsi: qla2xxx: Fix null pointer access during disconnect from subsystem
In reply to Greg Kroah-HartmanFrom: Quinn Tran <[email protected]>
[ Upstream commit 83949613fac61e8e37eadf8275bf072342302f4e ]
NVMEAsync command is being submitted to QLA while the same NVMe controller is in the middle of reset. The reset path has deleted the association and freed aen_op->fcp_req.private. Add a check for this private pointer before issuing the command.
...
6 [ffffb656ca11fce0] page_fault at ffffffff8c00114e
[exception RIP: qla_nvme_post_cmd+394]
RIP: ffffffffc0d012ba RSP: ffffb656ca11fd98 RFLAGS: 00010206
RAX: ffff8fb039eda228 RBX: ffff8fb039eda200 RCX: 00000000000da161
RDX: ffffffffc0d4d0f0 RSI: ffffffffc0d26c9b RDI: ffff8fb039eda220
RBP: 0000000000000013 R8: ffff8fb47ff6aa80 R9: 0000000000000002
R10: 0000000000000000 R11: ffffb656ca11fdc8 R12: ffff8fb27d04a3b0
R13: ffff8fc46dd98a58 R14: 0000000000000000 R15: ffff8fc4540f0000
ORIG_RAX: ffffffffffffffff CS: 0010 SS: 0018 7 [ffffb656ca11fe08] nvme_fc_start_fcp_op at ffffffffc0241568 [nvme_fc] 8 [ffffb656ca11fe50] nvme_fc_submit_async_event at ffffffffc0241901 [nvme_fc] 9 [ffffb656ca11fe68] nvme_async_event_work at ffffffffc014543d [nvme_core]
10 [ffffb656ca11fe98] process_one_work at ffffffff8b6cd437
11 [ffffb656ca11fed8] worker_thread at ffffffff8b6cdcef
12 [ffffb656ca11ff10] kthread at ffffffff8b6d3402
13 [ffffb656ca11ff50] ret_from_fork at ffffffff8c000255
--
PID: 37824 TASK: ffff8fb033063d80 CPU: 20 COMMAND: "kworker/u97:451"
0 [ffffb656ce1abc28] __schedule at ffffffff8be629e3
1 [ffffb656ce1abcc8] schedule at ffffffff8be62fe8
2 [ffffb656ce1abcd0] schedule_timeout at ffffffff8be671ed
3 [ffffb656ce1abd70] wait_for_completion at ffffffff8be639cf
4 [ffffb656ce1abdd0] flush_work at ffffffff8b6ce2d5
5 [ffffb656ce1abe70] nvme_stop_ctrl at ffffffffc0144900 [nvme_core] 6 [ffffb656ce1abe80] nvme_fc_reset_ctrl_work at ffffffffc0243445 [nvme_fc] 7 [ffffb656ce1abe98] process_one_work at ffffffff8b6cd437
8 [ffffb656ce1abed8] worker_thread at ffffffff8b6cdb50
9 [ffffb656ce1abf10] kthread at ffffffff8b6d3402
10 [ffffb656ce1abf50] ret_from_fork at ffffffff8c000255
--- drivers/scsi/qla2xxx/qla_nvme.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/scsi/qla2xxx/qla_nvme.c +5 -0
@@ -536,6 +536,11 @@ static int qla_nvme_post_cmd(struct nvme_fc_local_port *lport,struct nvme_private *priv = fd->private;struct qla_nvme_rport *qla_rport = rport->private; +if (!priv) { +/* nvme association has been torn down */ +return rval; + } + fcport = qla_rport->fcport; if (!qpair || !fcport || (qpair && !qpair->fw_started) ||
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 154/255 Revert "scsi: qla2xxx: Fix crash on qla2x00_mailbox_command"
In reply to Greg Kroah-HartmanFrom: Saurav Kashyap <[email protected]>
[ Upstream commit de7e6194301ad31c4ce95395eb678e51a1b907e5 ]
FCoE adapter initialization failed for ISP8021 with the following patch applied. In addition, reproduction of the issue the patch originally tried to address has been unsuccessful.
This reverts commit 3cb182b3fa8b7a61f05c671525494697cba39c6a.
--- drivers/scsi/qla2xxx/qla_mbx.c | 8 -------- 1 file changed, 8 deletions(-)
drivers/scsi/qla2xxx/qla_mbx.c +0 -8
@@ -333,14 +333,6 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)if (time_after (jiffies, wait_time))break ; -/* -* Check if it's UNLOADING, cause we cannot poll in -* this case, or else a NULL pointer dereference -* is triggered. -*/ -if (unlikely (test_bit (UNLOADING , &base_vha->dpc_flags))) -return QLA_FUNCTION_TIMEOUT ; -/* Check for pending interrupts. */ qla2x00_poll (ha->rsp_q_map[0 ]);
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 155/255 macvlan: validate setting of multiple remote source MAC addresses
In reply to Greg Kroah-HartmanFrom: Alvin Šipraga <[email protected]>
[ Upstream commit 8b61fba503904acae24aeb2bd5569b4d6544d48f ]
Remote source MAC addresses can be set on a 'source mode' macvlan interface via the IFLA_MACVLAN_MACADDR_DATA attribute. This commit tightens the validation of these MAC addresses to match the validation already performed when setting or adding a single MAC address via the IFLA_MACVLAN_MACADDR attribute.
iproute2 uses IFLA_MACVLAN_MACADDR_DATA for its 'macvlan macaddr set' command, and IFLA_MACVLAN_MACADDR for its 'macvlan macaddr add' command, which demonstrates the inconsistent behaviour that this commit addresses:
# ip link add link eth0 name macvlan0 type macvlan mode source
# ip link set link dev macvlan0 type macvlan macaddr add 01:00:00:00:00:00
RTNETLINK answers: Cannot assign requested address
# ip link set link dev macvlan0 type macvlan macaddr set 01:00:00:00:00:00
# ip -d link show macvlan0
5: macvlan0@eth0: <BROADCAST,MULTICAST,DYNAMIC,UP,LOWER_UP> mtu 1500 ...
link/ether 2e:ac:fd:2d:69:f8 brd ff:ff:ff:ff:ff:ff promiscuity 0
macvlan mode source remotes (1) 01:00:00:00:00:00 numtxqueues 1 ...With this change, the 'set' command will (rightly) fail in the same way as the 'add' command.
--- drivers/net/macvlan.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-)
drivers/net/macvlan.c +17 -4
@@ -1269,6 +1269,9 @@ static void macvlan_port_destroy(struct net_device *dev)static int macvlan_validate (struct nlattr *tb[],struct nlattr *data[],struct netlink_ext_ack *extack) { +struct nlattr *nla, *head; +int rem, len; +if (tb[IFLA_ADDRESS ]) {if (nla_len (tb[IFLA_ADDRESS ]) !=ETH_ALEN )return -EINVAL ;
@@ -1316,6 +1319,20 @@ static int macvlan_validate(struct nlattr *tb[], struct nlattr *data[],return -EADDRNOTAVAIL ; } +if (data[IFLA_MACVLAN_MACADDR_DATA ]) { + head =nla_data (data[IFLA_MACVLAN_MACADDR_DATA ]); + len =nla_len (data[IFLA_MACVLAN_MACADDR_DATA ]); + +nla_for_each_attr (nla, head, len, rem) { +if (nla_type (nla) !=IFLA_MACVLAN_MACADDR || +nla_len (nla) !=ETH_ALEN ) +return -EINVAL ; + +if (!is_valid_ether_addr (nla_data (nla))) +return -EADDRNOTAVAIL ; + } + } +if (data[IFLA_MACVLAN_MACADDR_COUNT ])return -EINVAL ;
@@ -1372,10 +1389,6 @@ static int macvlan_changelink_sources(struct macvlan_dev *vlan, u32 mode, len =nla_len (data[IFLA_MACVLAN_MACADDR_DATA ]);nla_for_each_attr (nla, head, len, rem) { -if (nla_type (nla) !=IFLA_MACVLAN_MACADDR || -nla_len (nla) !=ETH_ALEN ) -continue ; - addr =nla_data (nla); ret =macvlan_hash_add_source (vlan, addr);if (ret)
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 156/255 net: gianfar: Add of_node_put() before goto statement
In reply to Greg Kroah-HartmanFrom: Sumera Priyadarsini <[email protected]>
[ Upstream commit 989e4da042ca4a56bbaca9223d1a93639ad11e17 ]
Every iteration of for_each_available_child_of_node() decrements reference count of the previous node, however when control is transferred from the middle of the loop, as in the case of a return or break or goto, there is no decrement thus ultimately resulting in a memory leak.
Fix a potential memory leak in gianfar.c by inserting of_node_put() before the goto statement.
Issue found with Coccinelle.
--- drivers/net/ethernet/freescale/gianfar.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/net/ethernet/freescale/gianfar.c +3 -1
@@ -750,8 +750,10 @@ static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev)continue ; err =gfar_parse_group (child, priv, model); -if (err) +if (err) { +of_node_put (child); goto err_grp_init; + } } }else {/* SQ_SG_MODE */ err =gfar_parse_group (np, priv, model);
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 157/255 drm/amdgpu: fix NULL pointer access issue when unloading driver
In reply to Greg Kroah-HartmanFrom: Guchun Chen <[email protected]>
[ Upstream commit 1a68d96f81b8e7eb2a121fbf9abf9e5974e58832 ]
When unloading driver by "modprobe -r amdgpu", one NULL pointer dereference bug occurs in ras debugfs releasing. The cause is the duplicated debugfs_remove, as drm debugfs_root dir has been cleaned up already by drm_minor_unregister.
BUG: kernel NULL pointer dereference, address: 00000000000000a0 PGD 0 P4D 0 Oops: 0002 [#1] SMP PTI CPU: 11 PID: 1526 Comm: modprobe Tainted: G OE 5.6.0-guchchen #1 Hardware name: System manufacturer System Product Name/TUF Z370-PLUS GAMING II, BIOS 0411 09/21/2018 RIP: 0010:down_write+0x15/0x40 Code: eb de e8 7e 17 72 ff cc cc cc cc cc cc cc cc cc cc cc cc cc cc 0f 1f 44 00 00 53 48 89 fb e8 92 d8 ff ff 31 c0 ba 01 00 00 00 <f0> 48 0f b1 13 75 0f 65 48 8b 04 25 c0 8b 01 00 48 89 43 08 5b c3 RSP: 0018:ffffb1590386fcd0 EFLAGS: 00010246 RAX: 0000000000000000 RBX: 00000000000000a0 RCX: 0000000000000000 RDX: 0000000000000001 RSI: ffffffff85b2fcc2 RDI: 00000000000000a0 RBP: ffffb1590386fd30 R08: ffffffff85b2fcc2 R09: 000000000002b3c0 R10: ffff97a330618c40 R11: 00000000000005f6 R12: ffff97a3481beb40 R13: 00000000000000a0 R14: ffff97a3481beb40 R15: 0000000000000000 FS: 00007fb11a717540(0000) GS:ffff97a376cc0000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00000000000000a0 CR3: 00000004066d6006 CR4: 00000000003606e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Call Trace: simple_recursive_removal+0x63/0x370 ? debugfs_remove+0x60/0x60 debugfs_remove+0x40/0x60 amdgpu_ras_fini+0x82/0x230 [amdgpu] ? __kernfs_remove.part.17+0x101/0x1f0 ? kernfs_name_hash+0x12/0x80 amdgpu_device_fini+0x1c0/0x580 [amdgpu] amdgpu_driver_unload_kms+0x3e/0x70 [amdgpu] amdgpu_pci_remove+0x36/0x60 [amdgpu] pci_device_remove+0x3b/0xb0 device_release_driver_internal+0xe5/0x1c0 driver_detach+0x46/0x90 bus_remove_driver+0x58/0xd0 pci_unregister_driver+0x29/0x90 amdgpu_exit+0x11/0x25 [amdgpu] __x64_sys_delete_module+0x13d/0x210 do_syscall_64+0x5f/0x250 entry_SYSCALL_64_after_hwframe+0x44/0xa9
--- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 2 -- 1 file changed, 2 deletions(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +0 -2
@@ -1240,7 +1240,6 @@ void amdgpu_ras_debugfs_remove(struct amdgpu_device *adev,if (!obj || !obj->ent)return ; -debugfs_remove (obj->ent); obj->ent =NULL ;put_obj (obj); }
@@ -1254,7 +1253,6 @@ static void amdgpu_ras_debugfs_remove_all(struct amdgpu_device *adev)amdgpu_ras_debugfs_remove (adev, &obj->head); } -debugfs_remove_recursive (con->dir); con->dir =NULL ; }/* debugfs end */
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 158/255 drm/amdkfd: fix the wrong sdma instance query for renoir
In reply to Greg Kroah-HartmanFrom: Huang Rui <[email protected]>
[ Upstream commit 34174b89bfa495bed9cddcc504fb38feca90fab7 ]
Renoir only has one sdma instance, it will get failed once query the sdma1 registers. So use switch-case instead of static register array.
--- .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c | 31 +++++++++++++------ 1 file changed, 22 insertions(+), 9 deletions(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c +22 -9
@@ -195,19 +195,32 @@ static uint32_t get_sdma_rlc_reg_offset(struct amdgpu_device *adev,unsigned int engine_id, unsigned int queue_id) { - uint32_t sdma_engine_reg_base[2] = { -SOC15_REG_OFFSET (SDMA0 ,0 , - mmSDMA0_RLC0_RB_CNTL) - mmSDMA0_RLC0_RB_CNTL, -SOC15_REG_OFFSET (SDMA1 ,0 , - mmSDMA1_RLC0_RB_CNTL) - mmSDMA1_RLC0_RB_CNTL - }; -uint32_t retval = sdma_engine_reg_base[engine_id] + uint32_t sdma_engine_reg_base = 0; +uint32_t sdma_rlc_reg_offset; + +switch (engine_id) { +default : +dev_warn (adev->dev, +"Invalid sdma engine id (%d), using engine id 0\n" , + engine_id); + fallthrough; +case 0 : + sdma_engine_reg_base =SOC15_REG_OFFSET (SDMA0 ,0 , + mmSDMA0_RLC0_RB_CNTL) - mmSDMA0_RLC0_RB_CNTL; +break ; +case 1 : + sdma_engine_reg_base =SOC15_REG_OFFSET (SDMA1 ,0 , + mmSDMA1_RLC0_RB_CNTL) - mmSDMA0_RLC0_RB_CNTL; +break ; + } + + sdma_rlc_reg_offset = sdma_engine_reg_base + queue_id * (mmSDMA0_RLC1_RB_CNTL - mmSDMA0_RLC0_RB_CNTL);pr_debug ("RLC register offset for SDMA%d RLC%d: 0x%x\n" , engine_id, - queue_id, retval); + queue_id, sdma_rlc_reg_offset); -return retval; +return sdma_rlc_reg_offset; }static inline struct v9_mqd *get_mqd (void *mqd)
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 159/255 bpf: Fix a rcu_sched stall issue with bpf task/task_file iterator
In reply to Greg Kroah-HartmanFrom: Yonghong Song <[email protected]>
[ Upstream commit e679654a704e5bd676ea6446fa7b764cbabf168a ]
In our production system, we observed rcu stalls when 'bpftool prog` is running.
rcu: INFO: rcu_sched self-detected stall on CPU rcu: \x097-....: (20999 ticks this GP) idle=302/1/0x4000000000000000 softirq=1508852/1508852 fqs=4913 \x09(t=21031 jiffies g=2534773 q=179750) NMI backtrace for cpu 7 CPU: 7 PID: 184195 Comm: bpftool Kdump: loaded Tainted: G W 5.8.0-00004-g68bfc7f8c1b4 #6 Hardware name: Quanta Twin Lakes MP/Twin Lakes Passive MP, BIOS F09_3A17 05/03/2019 Call Trace: <IRQ> dump_stack+0x57/0x70 nmi_cpu_backtrace.cold+0x14/0x53 ? lapic_can_unplug_cpu.cold+0x39/0x39 nmi_trigger_cpumask_backtrace+0xb7/0xc7 rcu_dump_cpu_stacks+0xa2/0xd0 rcu_sched_clock_irq.cold+0x1ff/0x3d9 ? tick_nohz_handler+0x100/0x100 update_process_times+0x5b/0x90 tick_sched_timer+0x5e/0xf0 __hrtimer_run_queues+0x12a/0x2a0 hrtimer_interrupt+0x10e/0x280 __sysvec_apic_timer_interrupt+0x51/0xe0 asm_call_on_stack+0xf/0x20 </IRQ> sysvec_apic_timer_interrupt+0x6f/0x80 asm_sysvec_apic_timer_interrupt+0x12/0x20 RIP: 0010:task_file_seq_get_next+0x71/0x220 Code: 00 00 8b 53 1c 49 8b 7d 00 89 d6 48 8b 47 20 44 8b 18 41 39 d3 76 75 48 8b 4f 20 8b 01 39 d0 76 61 41 89 d1 49 39 c1 48 19 c0 <48> 8b 49 08 21 d0 48 8d 04 c1 4c 8b 08 4d 85 c9 74 46 49 8b 41 38 RSP: 0018:ffffc90006223e10 EFLAGS: 00000297 RAX: ffffffffffffffff RBX: ffff888f0d172388 RCX: ffff888c8c07c1c0 RDX: 00000000000f017b RSI: 00000000000f017b RDI: ffff888c254702c0 RBP: ffffc90006223e68 R08: ffff888be2a1c140 R09: 00000000000f017b R10: 0000000000000002 R11: 0000000000100000 R12: ffff888f23c24118 R13: ffffc90006223e60 R14: ffffffff828509a0 R15: 00000000ffffffff task_file_seq_next+0x52/0xa0 bpf_seq_read+0xb9/0x320 vfs_read+0x9d/0x180 ksys_read+0x5f/0xe0 do_syscall_64+0x38/0x60 entry_SYSCALL_64_after_hwframe+0x44/0xa9 RIP: 0033:0x7f8815f4f76e Code: c0 e9 f6 fe ff ff 55 48 8d 3d 76 70 0a 00 48 89 e5 e8 36 06 02 00 66 0f 1f 44 00 00 64 8b 04 25 18 00 00 00 85 c0 75 14 0f 05 <48> 3d 00 f0 ff ff 77 52 c3 66 0f 1f 84 00 00 00 00 00 55 48 89 e5 RSP: 002b:00007fff8f9df578 EFLAGS: 00000246 ORIG_RAX: 0000000000000000 RAX: ffffffffffffffda RBX: 000000000170b9c0 RCX: 00007f8815f4f76e RDX: 0000000000001000 RSI: 00007fff8f9df5b0 RDI: 0000000000000007 RBP: 00007fff8f9e05f0 R08: 0000000000000049 R09: 0000000000000010 R10: 00007f881601fa40 R11: 0000000000000246 R12: 00007fff8f9e05a8 R13: 00007fff8f9e05a8 R14: 0000000001917f90 R15: 000000000000e22e
Note that bpftool prog actually calls a task_file bpf iterator program to establish an association between prog/map/link/btf anon files and processes.
In the case where the above rcu stall occured, we had a process having 1587 tasks and each task having roughly 81305 files. This implied 129 million bpf prog invocations. Unfortunwtely none of these files are prog/map/link/btf files so bpf iterator/prog needs to traverse all these files and not able to return to user space since there are no seq_file buffer overflow.
This patch fixed the issue in bpf_seq_read() to limit the number of visited objects. If the maximum number of visited objects is reached, no more objects will be visited in the current syscall. If there is nothing written in the seq_file buffer, -EAGAIN will return to the user so user can try again.
The maximum number of visited objects is set at 1 million. In our Intel Xeon D-2191 2.3GHZ 18-core server, bpf_seq_read() visiting 1 million files takes around 0.18 seconds.
We did not use cond_resched() since for some iterators, e.g., netlink iterator, where rcu read_lock critical section spans between consecutive seq_ops->next(), which makes impossible to do cond_resched() in the key while loop of function bpf_seq_read().
--- kernel/bpf/bpf_iter.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-)
kernel/bpf/bpf_iter.c +14 -1
@@ -64,6 +64,9 @@ static void bpf_iter_done_stop(struct seq_file *seq) iter_priv->done_stop = true; } +/* maximum visited objects before bailing out */ +#define MAX_ITER_OBJECTS 1000000 +/* bpf_seq_read, a customized and simpler version for bpf iterator. * no_llseek is assumed for this file. * The following are differences from seq_read():
@@ -76,7 +79,7 @@ static ssize_t bpf_seq_read(struct file *file, char __user *buf, size_t size, {struct seq_file *seq = file->private_data;size_t n, offs, copied =0 ; -int err =0 ; +int err =0 , num_objs =0 ;void *p;mutex_lock (&seq->lock);
@@ -132,6 +135,7 @@ static ssize_t bpf_seq_read(struct file *file, char __user *buf, size_t size,while (1 ) {loff_t pos = seq->index; + num_objs++; offs = seq->count; p = seq->op->next (seq, p, &seq->index);if (pos == seq->index) {
@@ -150,6 +154,15 @@ static ssize_t bpf_seq_read(struct file *file, char __user *buf, size_t size,if (seq->count >= size)break ; +if (num_objs >=MAX_ITER_OBJECTS ) { +if (offs ==0 ) { + err = -EAGAIN ; + seq->op->stop (seq, p); + goto done; + } +break ; + } + err = seq->op->show (seq, p);if (err >0 ) {bpf_iter_dec_seq_num (seq);
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 160/255 bpf: Avoid visit same object multiple times
In reply to Greg Kroah-HartmanFrom: Yonghong Song <[email protected]>
[ Upstream commit e60572b8d4c39572be6857d1ec91fdf979f8775f ]
Currently when traversing all tasks, the next tid is always increased by one. This may result in visiting the same task multiple times in a pid namespace.
This patch fixed the issue by seting the next tid as pid_nr_ns(pid, ns) + 1, similar to funciton next_tgid().
--- kernel/bpf/task_iter.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
kernel/bpf/task_iter.c +2 -1
@@ -28,8 +28,9 @@ static struct task_struct *task_seq_get_next(struct pid_namespace *ns,rcu_read_lock (); retry: - pid =idr_get_next (&ns->idr, tid); + pid =find_ge_pid (*tid, ns);if (pid) { + *tid =pid_nr_ns (pid, ns); task =get_pid_task (pid,PIDTYPE_PID );if (!task) { ++*tid;
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 161/255 ext4: limit the length of per-inode prealloc list
In reply to Greg Kroah-HartmanFrom: brookxu <[email protected]>
[ Upstream commit 27bc446e2def38db3244a6eb4bb1d6312936610a ]
In the scenario of writing sparse files, the per-inode prealloc list may be very long, resulting in high overhead for ext4_mb_use_preallocated(). To circumvent this problem, we limit the maximum length of per-inode prealloc list to 512 and allow users to modify it.
After patching, we observed that the sys ratio of cpu has dropped, and the system throughput has increased significantly. We created a process to write the sparse file, and the running time of the process on the fixed kernel was significantly reduced, as follows:
Running time on unfixed kernel:
[root@TENCENT64 ~]# time taskset 0x01 ./sparse /data1/sparce.dat
real 0m2.051s user 0m0.008s sys 0m2.026s
Running time on fixed kernel:
[root@TENCENT64 ~]# time taskset 0x01 ./sparse /data1/sparce.dat
real 0m0.471s user 0m0.004s sys 0m0.395s
--- Documentation/admin-guide/ext4.rst | 3 ++ fs/ext4/ext4.h | 4 +- fs/ext4/extents.c | 10 ++-- fs/ext4/file.c | 2 +- fs/ext4/indirect.c | 2 +- fs/ext4/inode.c | 6 +-- fs/ext4/ioctl.c | 2 +- fs/ext4/mballoc.c | 74 ++++++++++++++++++++++++++---- fs/ext4/mballoc.h | 4 ++ fs/ext4/move_extent.c | 4 +- fs/ext4/super.c | 3 +- fs/ext4/sysfs.c | 2 + include/trace/events/ext4.h | 17 ++++--- 13 files changed, 104 insertions(+), 29 deletions(-)
Documentation/admin-guide/ext4.rst +3 -0
@@ -482,6 +482,9 @@ Files in /sys/fs/ext4/<devname>: multiple of this tuning parameter if the stripe size is not set in the ext4 superblock + mb_max_inode_prealloc + The maximum length of per-inode ext4_prealloc_space list. + mb_max_to_scan The maximum number of extents the multiblock allocator will search to find the best extent.
fs/ext4/ext4.h +3 -1
@@ -1054,6 +1054,7 @@ struct ext4_inode_info {struct timespec64 i_crtime;/* mballoc */ +atomic_t i_prealloc_active;struct list_head i_prealloc_list;spinlock_t i_prealloc_lock;
@@ -1501,6 +1502,7 @@ struct ext4_sb_info {unsigned int s_mb_stats;unsigned int s_mb_order2_reqs;unsigned int s_mb_group_prealloc; +unsigned int s_mb_max_inode_prealloc;unsigned int s_max_dir_size_kb;/* where last allocation was done - for stream allocation */ unsigned long s_mb_last_group;
@@ -2654,7 +2656,7 @@ extern int ext4_mb_release(struct super_block *);extern ext4_fsblk_t ext4_mb_new_blocks (handle_t *,struct ext4_allocation_request *,int *);extern int ext4_mb_reserve_blocks (struct super_block *,int ); -extern void ext4_discard_preallocations (struct inode *); +extern void ext4_discard_preallocations (struct inode *,unsigned int );extern int __init ext4_init_mballoc (void );extern void ext4_exit_mballoc (void ); extern void ext4_free_blocks(handle_t *handle, struct inode *inode,
fs/ext4/extents.c +5 -5
@@ -100,7 +100,7 @@ static int ext4_ext_trunc_restart_fn(struct inode *inode, int *dropped)* i_mutex. So we can safely drop the i_data_sem here. */ BUG_ON (EXT4_JOURNAL (inode) ==NULL ); -ext4_discard_preallocations (inode); +ext4_discard_preallocations (inode,0 );up_write (&EXT4_I (inode)->i_data_sem); *dropped =1 ;return 0 ;
@@ -4268,7 +4268,7 @@ got_allocated_blocks:* not a good idea to call discard here directly, * but otherwise we'd need to call it every free(). */ -ext4_discard_preallocations (inode); +ext4_discard_preallocations (inode,0 );if (flags &EXT4_GET_BLOCKS_DELALLOC_RESERVE ) fb_flags =EXT4_FREE_BLOCKS_NO_QUOT_UPDATE ; ext4_free_blocks(handle, inode, NULL, newblock,
@@ -5295,7 +5295,7 @@ static int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len) }down_write (&EXT4_I (inode)->i_data_sem); -ext4_discard_preallocations (inode); +ext4_discard_preallocations (inode,0 ); ret =ext4_es_remove_extent (inode, punch_start,EXT_MAX_BLOCKS - punch_start);
@@ -5309,7 +5309,7 @@ static int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len)up_write (&EXT4_I (inode)->i_data_sem); goto out_stop; } -ext4_discard_preallocations (inode); +ext4_discard_preallocations (inode,0 ); ret =ext4_ext_shift_extents (inode, handle, punch_stop, punch_stop - punch_start,SHIFT_LEFT );
@@ -5441,7 +5441,7 @@ static int ext4_insert_range(struct inode *inode, loff_t offset, loff_t len) goto out_stop;down_write (&EXT4_I (inode)->i_data_sem); -ext4_discard_preallocations (inode); +ext4_discard_preallocations (inode,0 ); path =ext4_find_extent (inode, offset_lblk,NULL ,0 );if (IS_ERR (path)) {
fs/ext4/file.c +1 -1
@@ -148,7 +148,7 @@ static int ext4_release_file(struct inode *inode, struct file *filp) !EXT4_I(inode)->i_reserved_data_blocks) {down_write (&EXT4_I (inode)->i_data_sem); -ext4_discard_preallocations (inode); +ext4_discard_preallocations (inode,0 );up_write (&EXT4_I (inode)->i_data_sem); }if (is_dx (inode) && filp->private_data)
fs/ext4/indirect.c +1 -1
@@ -696,7 +696,7 @@ static int ext4_ind_trunc_restart_fn(handle_t *handle, struct inode *inode,* i_mutex. So we can safely drop the i_data_sem here. */ BUG_ON (EXT4_JOURNAL (inode) ==NULL ); -ext4_discard_preallocations (inode); +ext4_discard_preallocations (inode,0 );up_write (&EXT4_I (inode)->i_data_sem); *dropped =1 ;return 0 ;
fs/ext4/inode.c +3 -3
@@ -383,7 +383,7 @@ void ext4_da_update_reserve_space(struct inode *inode,*/ if ((ei->i_reserved_data_blocks ==0 ) && !inode_is_open_for_write (inode)) -ext4_discard_preallocations (inode); +ext4_discard_preallocations (inode,0 ); } static int __check_block_validity(struct inode *inode, const char *func,
@@ -4055,7 +4055,7 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length)if (stop_block > first_block) {down_write (&EXT4_I (inode)->i_data_sem); -ext4_discard_preallocations (inode); +ext4_discard_preallocations (inode,0 ); ret =ext4_es_remove_extent (inode, first_block, stop_block - first_block);
@@ -4210,7 +4210,7 @@ int ext4_truncate(struct inode *inode)down_write (&EXT4_I (inode)->i_data_sem); -ext4_discard_preallocations (inode); +ext4_discard_preallocations (inode,0 );if (ext4_test_inode_flag (inode,EXT4_INODE_EXTENTS )) err =ext4_ext_truncate (handle, inode);
fs/ext4/ioctl.c +1 -1
@@ -202,7 +202,7 @@ static long swap_inode_boot_loader(struct super_block *sb,reset_inode_seed (inode);reset_inode_seed (inode_bl); -ext4_discard_preallocations (inode); +ext4_discard_preallocations (inode,0 ); err =ext4_mark_inode_dirty (handle, inode);if (err <0 ) {
fs/ext4/mballoc.c +66 -8
160 lines not on this page · raw message
fs/ext4/mballoc.h +4 -0
@@ -73,6 +73,10 @@*/ #define MB_DEFAULT_GROUP_PREALLOC 512 +/* +* maximum length of inode prealloc list +*/ +#define MB_DEFAULT_MAX_INODE_PREALLOC 512struct ext4_free_data {/* this links the free block information from sb_info */
fs/ext4/move_extent.c +2 -2
@@ -686,8 +686,8 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, __u64 orig_blk, out:if (*moved_len) { -ext4_discard_preallocations (orig_inode); -ext4_discard_preallocations (donor_inode); +ext4_discard_preallocations (orig_inode,0 ); +ext4_discard_preallocations (donor_inode,0 ); }ext4_ext_drop_refs (path);
fs/ext4/super.c +2 -1
@@ -1123,6 +1123,7 @@ static struct inode *ext4_alloc_inode(struct super_block *sb)inode_set_iversion (&ei->vfs_inode,1 );spin_lock_init (&ei->i_raw_lock);INIT_LIST_HEAD (&ei->i_prealloc_list); +atomic_set (&ei->i_prealloc_active,0 );spin_lock_init (&ei->i_prealloc_lock);ext4_es_init_tree (&ei->i_es_tree);rwlock_init (&ei->i_es_lock);
@@ -1216,7 +1217,7 @@ void ext4_clear_inode(struct inode *inode) {invalidate_inode_buffers (inode);clear_inode (inode); -ext4_discard_preallocations (inode); +ext4_discard_preallocations (inode,0 );ext4_es_remove_extent (inode,0 ,EXT_MAX_BLOCKS );dquot_drop (inode);if (EXT4_I (inode)->jinode) {
fs/ext4/sysfs.c +2 -0
@@ -215,6 +215,7 @@ EXT4_RW_ATTR_SBI_UI(mb_min_to_scan, s_mb_min_to_scan);EXT4_RW_ATTR_SBI_UI (mb_order2_req, s_mb_order2_reqs);EXT4_RW_ATTR_SBI_UI (mb_stream_req, s_mb_stream_request);EXT4_RW_ATTR_SBI_UI (mb_group_prealloc, s_mb_group_prealloc); +EXT4_RW_ATTR_SBI_UI (mb_max_inode_prealloc, s_mb_max_inode_prealloc);EXT4_RW_ATTR_SBI_UI (extent_max_zeroout_kb, s_extent_max_zeroout_kb);EXT4_ATTR (trigger_fs_error,0200 , trigger_test_error);EXT4_RW_ATTR_SBI_UI (err_ratelimit_interval_ms, s_err_ratelimit_state.interval);
@@ -257,6 +258,7 @@ static struct attribute *ext4_attrs[] = {ATTR_LIST (mb_order2_req),ATTR_LIST (mb_stream_req),ATTR_LIST (mb_group_prealloc), +ATTR_LIST (mb_max_inode_prealloc),ATTR_LIST (max_writeback_mb_bump),ATTR_LIST (extent_max_zeroout_kb), ATTR_LIST(trigger_fs_error),
include/trace/events/ext4.h +11 -6
@@ -746,24 +746,29 @@ TRACE_EVENT(ext4_mb_release_group_pa, );TRACE_EVENT (ext4_discard_preallocations, - TP_PROTO(struct inode *inode), + TP_PROTO(struct inode *inode, unsigned int len, unsigned int needed), -TP_ARGS (inode), +TP_ARGS (inode, len, needed),TP_STRUCT__entry ( - __field( dev_t, dev ) -__field ( ino_t, ino ) + __field( dev_t, dev ) + __field( ino_t, ino ) + __field( unsigned int, len ) + __field( unsigned int, needed ) ),TP_fast_assign ( __entry->dev = inode->i_sb->s_dev; __entry->ino = inode->i_ino; + __entry->len = len; + __entry->needed = needed; ), -TP_printk ("dev %d,%d ino %lu" , +TP_printk ("dev %d,%d ino %lu len: %u needed %u" ,MAJOR (__entry->dev),MINOR (__entry->dev), - (unsigned long ) __entry->ino) + (unsigned long ) __entry->ino, __entry->len, + __entry->needed) ); TRACE_EVENT(ext4_mb_discard_preallocations,
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 162/255 powerpc/perf: Fix soft lockups due to missed interrupt accounting
In reply to Greg Kroah-HartmanFrom: Athira Rajeev <[email protected]>
[ Upstream commit 17899eaf88d689529b866371344c8f269ba79b5f ]
Performance monitor interrupt handler checks if any counter has overflown and calls record_and_restart() in core-book3s which invokes perf_event_overflow() to record the sample information. Apart from creating sample, perf_event_overflow() also does the interrupt and period checks via perf_event_account_interrupt().
Currently we record information only if the SIAR (Sampled Instruction Address Register) valid bit is set (using siar_valid() check) and hence the interrupt check.
But it is possible that we do sampling for some events that are not generating valid SIAR, and hence there is no chance to disable the event if interrupts are more than max_samples_per_tick. This leads to soft lockup.
Fix this by adding perf_event_account_interrupt() in the invalid SIAR code path for a sampling event. ie if SIAR is invalid, just do interrupt check and don't record the sample information.
--- arch/powerpc/perf/core-book3s.c | 4 ++++ 1 file changed, 4 insertions(+)
arch/powerpc/perf/core-book3s.c +4 -0
@@ -2101,6 +2101,10 @@ static void record_and_restart(struct perf_event *event, unsigned long val,if (perf_event_overflow (event, &data, regs))power_pmu_stop (event,0 ); + }else if (period) { +/* Account for interrupt in case of invalid SIAR */ +if (perf_event_account_interrupt (event)) +power_pmu_stop (event,0 ); } }
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 163/255 libbpf: Fix map index used in error message
In reply to Greg Kroah-HartmanFrom: Toke Høiland-Jørgensen <[email protected]>
[ Upstream commit 1e891e513e16c145cc9b45b1fdb8bf4a4f2f9557 ]
The error message emitted by bpf_object__init_user_btf_maps() was using the wrong section ID.
--- tools/lib/bpf/libbpf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/lib/bpf/libbpf.c +1 -1
@@ -2237,7 +2237,7 @@ static int bpf_object__init_user_btf_maps(struct bpf_object *obj, bool strict, data =elf_getdata (scn,NULL );if (!scn || !data) {pr_warn ("failed to get Elf_Data from map section %d (%s)\n" , - obj->efile.maps_shndx,MAPS_ELF_SEC ); + obj->efile.btf_maps_shndx,MAPS_ELF_SEC );return -EINVAL ; }
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 164/255 bpf: selftests: global_funcs: Check err_str before strstr
In reply to Greg Kroah-HartmanFrom: Yauheni Kaliuta <[email protected]>
[ Upstream commit c210773d6c6f595f5922d56b7391fe343bc7310e ]
The error path in libbpf.c:load_program() has calls to pr_warn() which ends up for global_funcs tests to test_global_funcs.c:libbpf_debug_print().
For the tests with no struct test_def::err_str initialized with a string, it causes call of strstr() with NULL as the second argument and it segfaults.
Fix it by calling strstr() only for non-NULL err_str.
--- tools/testing/selftests/bpf/prog_tests/test_global_funcs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/testing/selftests/bpf/prog_tests/test_global_funcs.c +1 -1
@@ -19,7 +19,7 @@ static int libbpf_debug_print(enum libbpf_print_level level, log_buf = va_arg(args, char *);if (!log_buf) goto out; -if (strstr (log_buf, err_str) ==0 ) +if (err_str &&strstr (log_buf, err_str) ==0 ) found = true; out:printf (format, log_buf);
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 165/255 arm64: Move handling of erratum 1418040 into C code
In reply to Greg Kroah-HartmanFrom: Marc Zyngier <[email protected]>
[ Upstream commit d49f7d7376d0c0daf8680984a37bd07581ac7d38 ]
Instead of dealing with erratum 1418040 on each entry and exit, let's move the handling to __switch_to() instead, which has several advantages:
- It can be applied when it matters (switching between 32 and 64 bit tasks).
- It is written in C (yay!)
- It can rely on static keys rather than alternatives
--- arch/arm64/kernel/entry.S | 21 --------------------- arch/arm64/kernel/process.c | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 21 deletions(-)
arch/arm64/kernel/entry.S +0 -21
@@ -169,19 +169,6 @@ alternative_cb_end stp x28, x29, [sp, #16 * 14] .if \el == 0 - .if \regsize == 32 - /* - * If we're returning from a 32-bit task on a system affected by - * 1418040 then re-enable userspace access to the virtual counter. - */ -#ifdef CONFIG_ARM64_ERRATUM_1418040 -alternative_if ARM64_WORKAROUND_1418040 - mrs x0, cntkctl_el1 - orr x0, x0, #2 // ARCH_TIMER_USR_VCT_ACCESS_EN - msr cntkctl_el1, x0 -alternative_else_nop_endif -#endif - .endif clear_gp_regs mrs x21, sp_el0 ldr_this_cpu tsk, __entry_task, x20
@@ -337,14 +324,6 @@ alternative_else_nop_endif tst x22, #PSR_MODE32_BIT // native task? b.eq 3f -#ifdef CONFIG_ARM64_ERRATUM_1418040 -alternative_if ARM64_WORKAROUND_1418040 - mrs x0, cntkctl_el1 - bic x0, x0, #2 // ARCH_TIMER_USR_VCT_ACCESS_EN - msr cntkctl_el1, x0 -alternative_else_nop_endif -#endif - #ifdef CONFIG_ARM64_ERRATUM_845719 alternative_if ARM64_WORKAROUND_845719 #ifdef CONFIG_PID_IN_CONTEXTIDR
arch/arm64/kernel/process.c +34 -0
@@ -515,6 +515,39 @@ static void entry_task_switch(struct task_struct *next)__this_cpu_write (__entry_task, next); } +/* +* ARM erratum 1418040 handling, affecting the 32bit view of CNTVCT. +* Assuming the virtual counter is enabled at the beginning of times: +* +* - disable access when switching from a 64bit task to a 32bit task +* - enable access when switching from a 32bit task to a 64bit task +*/ +static void erratum_1418040_thread_switch (struct task_struct *prev, +struct task_struct *next) +{ +bool prev32, next32; +u64 val; + +if (!(IS_ENABLED (CONFIG_ARM64_ERRATUM_1418040 ) && +cpus_have_const_cap (ARM64_WORKAROUND_1418040 ))) +return ; + + prev32 =is_compat_thread (task_thread_info (prev)); + next32 =is_compat_thread (task_thread_info (next)); + +if (prev32 == next32) +return ; + + val =read_sysreg (cntkctl_el1); + +if (!next32) + val |=ARCH_TIMER_USR_VCT_ACCESS_EN ; +else + val &= ~ARCH_TIMER_USR_VCT_ACCESS_EN ; + +write_sysreg (val, cntkctl_el1); +} +/* * Thread switching. */
@@ -530,6 +563,7 @@ __notrace_funcgraph struct task_struct *__switch_to(struct task_struct *prev,entry_task_switch (next);uao_thread_switch (next);ssbs_thread_switch (next); +erratum_1418040_thread_switch (prev, next);/* * Complete any pending TLB or cache maintenance on this CPU in case
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 166/255 arm64: Allow booting of late CPUs affected by erratum 1418040
In reply to Greg Kroah-HartmanFrom: Marc Zyngier <[email protected]>
[ Upstream commit bf87bb0881d0f59181fe3bbcf29c609f36483ff8 ]
As we can now switch from a system that isn't affected by 1418040 to a system that globally is affected, let's allow affected CPUs to come in at a later time.
--- arch/arm64/kernel/cpu_errata.c | 2 ++ 1 file changed, 2 insertions(+)
arch/arm64/kernel/cpu_errata.c +2 -0
@@ -910,6 +910,8 @@ const struct arm64_cpu_capabilities arm64_errata[] = { .desc = "ARM erratum 1418040", .capability =ARM64_WORKAROUND_1418040 ,ERRATA_MIDR_RANGE_LIST (erratum_1418040_list), + .type = (ARM64_CPUCAP_SCOPE_LOCAL_CPU | +ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU ), }, #endif #ifdef CONFIG_ARM64_WORKAROUND_SPECULATIVE_AT
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 167/255 hwmon: (gsc-hwmon) Scale temperature to millidegrees
In reply to Greg Kroah-HartmanFrom: Tim Harvey <[email protected]>
commit c1ae18d313e24bc7833e1749dd36dba5d47f259c upstream.
The GSC registers report temperature in decidegrees celcius so we need to scale it to represent the hwmon sysfs API of millidegrees.
--- drivers/hwmon/gsc-hwmon.c | 1 + 1 file changed, 1 insertion(+)
drivers/hwmon/gsc-hwmon.c +1 -0
@@ -172,6 +172,7 @@ gsc_hwmon_read(struct device *dev, enumcase mode_temperature:if (tmp >0x8000 ) tmp -=0xffff ; + tmp *=100 ;/* convert to millidegrees celsius */ break ;case mode_voltage_raw: tmp =clamp_val (tmp,0 ,BIT (GSC_HWMON_RESOLUTION ));
Greg Kroah-Hartman
maintainerPATCH 168/255 block: fix get_max_io_size()
In reply to Greg Kroah-HartmanFrom: Keith Busch <[email protected]>
commit e4b469c66f3cbb81c2e94d31123d7bcdf3c1dabd upstream.
A previous commit aligning splits to physical block sizes inadvertently modified one return case such that that it now returns 0 length splits when the number of sectors doesn't exceed the physical offset. This later hits a BUG in bio_split(). Restore the previous working behavior.
--- block/blk-merge.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
block/blk-merge.c +1 -1
@@ -154,7 +154,7 @@ static inline unsigned get_max_io_size(sif (max_sectors > start_offset)return max_sectors - start_offset; -return sectors & (lbs -1 ); +return sectors & ~(lbs -1 ); } static inline unsigned get_max_segment_size(const struct request_queue *q,
Greg Kroah-Hartman
maintainerPATCH 169/255 block: loop: set discard granularity and alignment for block device backed loop
In reply to Greg Kroah-HartmanFrom: Ming Lei <[email protected]>
commit bcb21c8cc9947286211327d663ace69f07d37a76 upstream.
In case of block device backend, if the backend supports write zeros, the loop device will set queue flag of QUEUE_FLAG_DISCARD. However, limits.discard_granularity isn't setup, and this way is wrong, see the following description in Documentation/ABI/testing/sysfs-block:
A discard_granularity of 0 means that the device does not support discard functionality.
Especially 9b15d109a6b2 ("block: improve discard bio alignment in __blkdev_issue_discard()") starts to take q->limits.discard_granularity for computing max discard sectors. And zero discard granularity may cause kernel oops, or fail discard request even though the loop queue claims discard support via QUEUE_FLAG_DISCARD.
Fix the issue by setup discard granularity and alignment.
--- drivers/block/loop.c | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-)
drivers/block/loop.c +18 -15
@@ -877,6 +877,7 @@ static void loop_config_discard(struct lstruct file *file = lo->lo_backing_file;struct inode *inode = file->f_mapping->host;struct request_queue *q = lo->lo_queue; +u32 granularity, max_discard_sectors;/* * If the backing device is a block device, mirror its zeroing
@@ -889,11 +890,10 @@ static void loop_config_discard(struct lstruct request_queue *backingq; backingq =bdev_get_queue (inode->i_bdev); -blk_queue_max_discard_sectors (q, - backingq->limits.max_write_zeroes_sectors); -blk_queue_max_write_zeroes_sectors (q, - backingq->limits.max_write_zeroes_sectors); + max_discard_sectors = backingq->limits.max_write_zeroes_sectors; + granularity = backingq->limits.discard_granularity ?: +queue_physical_block_size (backingq);/* * We use punch hole to reclaim the free space used by the
@@ -902,23 +902,26 @@ static void loop_config_discard(struct l* useful information. */ }else if (!file->f_op->fallocate || lo->lo_encrypt_key_size) { - q->limits.discard_granularity =0 ; - q->limits.discard_alignment =0 ; -blk_queue_max_discard_sectors (q,0 ); -blk_queue_max_write_zeroes_sectors (q,0 ); + max_discard_sectors =0 ; + granularity =0 ; }else { - q->limits.discard_granularity = inode->i_sb->s_blocksize; - q->limits.discard_alignment =0 ; - -blk_queue_max_discard_sectors (q,UINT_MAX >>9 ); -blk_queue_max_write_zeroes_sectors (q,UINT_MAX >>9 ); + max_discard_sectors =UINT_MAX >>9 ; + granularity = inode->i_sb->s_blocksize; } -if (q->limits.max_write_zeroes_sectors) +if (max_discard_sectors) { + q->limits.discard_granularity = granularity; +blk_queue_max_discard_sectors (q, max_discard_sectors); +blk_queue_max_write_zeroes_sectors (q, max_discard_sectors);blk_queue_flag_set (QUEUE_FLAG_DISCARD , q); -else + }else { + q->limits.discard_granularity =0 ; +blk_queue_max_discard_sectors (q,0 ); +blk_queue_max_write_zeroes_sectors (q,0 );blk_queue_flag_clear (QUEUE_FLAG_DISCARD , q); + } + q->limits.discard_alignment =0 ; }static void loop_unprepare_queue (struct loop_device *lo)
Greg Kroah-Hartman
maintainerPATCH 170/255 HID: i2c-hid: Always sleep 60ms after I2C_HID_PWR_ON commands
In reply to Greg Kroah-HartmanFrom: Hans de Goede <[email protected]>
commit eef4016243e94c438f177ca8226876eb873b9c75 upstream.
Before this commit i2c_hid_parse() consists of the following steps:
1. Send power on cmd
2. usleep_range(1000, 5000)
3. Send reset cmd
4. Wait for reset to complete (device interrupt, or msleep(100))
5. Send power on cmd
6. Try to read HID descriptor
Notice how there is an usleep_range(1000, 5000) after the first power-on command, but not after the second power-on command.
Testing has shown that at least on the BMAX Y13 laptop's i2c-hid touchpad, not having a delay after the second power-on command causes the HID descriptor to read as all zeros.
In case we hit this on other devices too, the descriptor being all zeros can be recognized by the following message being logged many, many times:
hid-generic 0018:0911:5288.0002: unknown main item tag 0x0
At the same time as the BMAX Y13's touchpad issue was debugged, Kai-Heng was working on debugging some issues with Goodix i2c-hid touchpads. It turns out that these need a delay after a PWR_ON command too, otherwise they stop working after a suspend/resume cycle. According to Goodix a delay of minimal 60ms is needed.
Having multiple cases where we need a delay after sending the power-on command, seems to indicate that we should always sleep after the power-on command.
This commit fixes the mentioned issues by moving the existing 1ms sleep to the i2c_hid_set_power() function and changing it to a 60ms sleep.
--- drivers/hid/i2c-hid/i2c-hid-core.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-)
drivers/hid/i2c-hid/i2c-hid-core.c +13 -9
@@ -420,6 +420,19 @@ static int i2c_hid_set_power(struct i2c_dev_err (&client->dev,"failed to change power setting.\n" ); set_pwr_exit: + +/* +* The HID over I2C specification states that if a DEVICE needs time +* after the PWR_ON request, it should utilise CLOCK stretching. +* However, it has been observered that the Windows driver provides a +* 1ms sleep between the PWR_ON and RESET requests. +* According to Goodix Windows even waits 60 ms after (other?) +* PWR_ON requests. Testing has confirmed that several devices +* will not work properly without a delay after a PWR_ON request. +*/ +if (!ret && power_state ==I2C_HID_PWR_ON ) +msleep (60 ); +return ret; }
@@ -441,15 +454,6 @@ static int i2c_hid_hwreset(struct i2c_clif (ret) goto out_unlock; -/* -* The HID over I2C specification states that if a DEVICE needs time -* after the PWR_ON request, it should utilise CLOCK stretching. -* However, it has been observered that the Windows driver provides a -* 1ms sleep between the PWR_ON and RESET requests and that some devices -* rely on this. -*/ -usleep_range (1000 ,5000 ); -i2c_hid_dbg (ihid,"resetting...\n" ); ret =i2c_hid_command (client, &hid_reset_cmd,NULL ,0 );
Greg Kroah-Hartman
maintainerPATCH 171/255 blk-mq: order adding requests to hctx->dispatch and checking SCHED_RESTART
In reply to Greg Kroah-HartmanFrom: Ming Lei <[email protected]>
commit d7d8535f377e9ba87edbf7fbbd634ac942f3f54f upstream.
SCHED_RESTART code path is relied to re-run queue for dispatch requests in hctx->dispatch. Meantime the SCHED_RSTART flag is checked when adding requests to hctx->dispatch.
memory barriers have to be used for ordering the following two pair of OPs:
1) adding requests to hctx->dispatch and checking SCHED_RESTART in blk_mq_dispatch_rq_list()
2) clearing SCHED_RESTART and checking if there is request in hctx->dispatch in blk_mq_sched_restart().
Without the added memory barrier, either:
1) blk_mq_sched_restart() may miss requests added to hctx->dispatch meantime blk_mq_dispatch_rq_list() observes SCHED_RESTART, and not run queue in dispatch side
or
2) blk_mq_dispatch_rq_list still sees SCHED_RESTART, and not run queue in dispatch side, meantime checking if there is request in hctx->dispatch from blk_mq_sched_restart() is missed.
IO hang in ltp/fs_fill test is reported by kernel test robot:
https://lkml.org/lkml/2020/7/26/77
Turns out it is caused by the above out-of-order OPs. And the IO hang can't be observed any more after applying this patch.
--- block/blk-mq-sched.c | 9 +++++++++ block/blk-mq.c | 9 +++++++++ 2 files changed, 18 insertions(+)
block/blk-mq-sched.c +9 -0
@@ -77,6 +77,15 @@ void blk_mq_sched_restart(struct blk_mq_return ;clear_bit (BLK_MQ_S_SCHED_RESTART , &hctx->state); +/* +* Order clearing SCHED_RESTART and list_empty_careful(&hctx->dispatch) +* in blk_mq_run_hw_queue(). Its pair is the barrier in +* blk_mq_dispatch_rq_list(). So dispatch code won't see SCHED_RESTART, +* meantime new request added to hctx->dispatch is missed to check in +* blk_mq_run_hw_queue(). +*/ +smp_mb (); +blk_mq_run_hw_queue (hctx, true); }
block/blk-mq.c +9 -0
@@ -1324,6 +1324,15 @@ bool blk_mq_dispatch_rq_list(struct requspin_unlock (&hctx->lock);/* +* Order adding requests to hctx->dispatch and checking +* SCHED_RESTART flag. The pair of this smp_mb() is the one +* in blk_mq_sched_restart(). Avoid restart code path to +* miss the new added requests to hctx->dispatch, meantime +* SCHED_RESTART is observed here. +*/ +smp_mb (); + +/* * If SCHED_RESTART was set by the caller of this function and * it is no longer set that means that it was cleared by another * thread and hence that a queue rerun is needed.
Greg Kroah-Hartman
maintainerPATCH 172/255 btrfs: reset compression level for lzo on remount
In reply to Greg Kroah-HartmanFrom: Marcos Paulo de Souza <[email protected]>
commit 282dd7d7718444679b046b769d872b188818ca35 upstream.
Currently a user can set mount "-o compress" which will set the compression algorithm to zlib, and use the default compress level for zlib (3):
relatime,compress=zlib:3,space_cache
If the user remounts the fs using "-o compress=lzo", then the old compress_level is used:
relatime,compress=lzo:3,space_cache
But lzo does not expose any tunable compression level. The same happens if we set any compress argument with different level, also with zstd.
Fix this by resetting the compress_level when compress=lzo is specified. With the fix applied, lzo is shown without compress level:
relatime,compress=lzo,space_cache
--- fs/btrfs/super.c | 1 + 1 file changed, 1 insertion(+)
fs/btrfs/super.c +1 -0
@@ -558,6 +558,7 @@ int btrfs_parse_options(struct btrfs_fs_ }else if (strncmp (args[0 ].from,"lzo" ,3 ) ==0 ) { compress_type ="lzo" ; info->compress_type =BTRFS_COMPRESS_LZO ; + info->compress_level =0 ;btrfs_set_opt (info->mount_opt,COMPRESS );btrfs_clear_opt (info->mount_opt,NODATACOW );btrfs_clear_opt (info->mount_opt,NODATASUM );
Greg Kroah-Hartman
maintainerPATCH 173/255 btrfs: check the right error variable in btrfs_del_dir_entries_in_log
In reply to Greg Kroah-HartmanFrom: Josef Bacik <[email protected]>
commit fb2fecbad50964b9f27a3b182e74e437b40753ef upstream.
With my new locking code dbench is so much faster that I tripped over a transaction abort from ENOSPC. This turned out to be because btrfs_del_dir_entries_in_log was checking for ret == -ENOSPC, but this function sets err on error, and returns err. So instead of properly marking the inode as needing a full commit, we were returning -ENOSPC and aborting in __btrfs_unlink_inode. Fix this by checking the proper variable so that we return the correct thing in the case of ENOSPC.
The ENOENT needs to be checked, because btrfs_lookup_dir_item_index() can return -ENOENT if the dir item isn't in the tree log (which would happen if we hadn't fsync'ed this guy). We actually handle that case in __btrfs_unlink_inode, so it's an expected error to get back.
--- fs/btrfs/tree-log.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
fs/btrfs/tree-log.c +6 -4
@@ -3449,11 +3449,13 @@ fail:btrfs_free_path (path); out_unlock:mutex_unlock (&dir->log_mutex); -if (ret == -ENOSPC ) { +if (err == -ENOSPC ) {btrfs_set_log_full_commit (trans); - ret =0 ; - }else if (ret <0 ) -btrfs_abort_transaction (trans, ret); + err =0 ; + }else if (err <0 && err != -ENOENT ) { +/* ENOENT can be returned if the entry hasn't been fsynced yet */ +btrfs_abort_transaction (trans, err); + }btrfs_end_log_trans (root);
Greg Kroah-Hartman
maintainerPATCH 174/255 btrfs: fix space cache memory leak after transaction abort
In reply to Greg Kroah-HartmanFrom: Filipe Manana <[email protected]>
commit bbc37d6e475eee8ffa2156ec813efc6bbb43c06d upstream.
If a transaction aborts it can cause a memory leak of the pages array of a block group's io_ctl structure. The following steps explain how that can happen:
1) Transaction N is committing, currently in state TRANS_STATE_UNBLOCKED and it's about to start writing out dirty extent buffers;
2) Transaction N + 1 already started and another task, task A, just called btrfs_commit_transaction() on it;
3) Block group B was dirtied (extents allocated from it) by transaction N + 1, so when task A calls btrfs_start_dirty_block_groups(), at the very beginning of the transaction commit, it starts writeback for the block group's space cache by calling btrfs_write_out_cache(), which allocates the pages array for the block group's io_ctl with a call to io_ctl_init(). Block group A is added to the io_list of transaction N + 1 by btrfs_start_dirty_block_groups();
4) While transaction N's commit is writing out the extent buffers, it gets an IO error and aborts transaction N, also setting the file system to RO mode;
5) Task A has already returned from btrfs_start_dirty_block_groups(), is at btrfs_commit_transaction() and has set transaction N + 1 state to TRANS_STATE_COMMIT_START. Immediately after that it checks that the filesystem was turned to RO mode, due to transaction N's abort, and jumps to the "cleanup_transaction" label. After that we end up at btrfs_cleanup_one_transaction() which calls btrfs_cleanup_dirty_bgs(). That helper finds block group B in the transaction's io_list but it never releases the pages array of the block group's io_ctl, resulting in a memory leak.
In fact at the point when we are at btrfs_cleanup_dirty_bgs(), the pages array points to pages that were already released by us at __btrfs_write_out_cache() through the call to io_ctl_drop_pages(). We end up freeing the pages array only after waiting for the ordered extent to complete through btrfs_wait_cache_io(), which calls io_ctl_free() to do that. But in the transaction abort case we don't wait for the space cache's ordered extent to complete through a call to btrfs_wait_cache_io(), so that's why we end up with a memory leak - we wait for the ordered extent to complete indirectly by shutting down the work queues and waiting for any jobs in them to complete before returning from close_ctree().
We can solve the leak simply by freeing the pages array right after releasing the pages (with the call to io_ctl_drop_pages()) at __btrfs_write_out_cache(), since we will never use it anymore after that and the pages array points to already released pages at that point, which is currently not a problem since no one will use it after that, but not a good practice anyway since it can easily lead to use-after-free issues.
So fix this by freeing the pages array right after releasing the pages at __btrfs_write_out_cache().
This issue can often be reproduced with test case generic/475 from fstests and kmemleak can detect it and reports it with the following trace:
unreferenced object 0xffff9bbf009fa600 (size 512):
comm "fsstress", pid 38807, jiffies 4298504428 (age 22.028s) hex dump (first 32 bytes):
00 a0 7c 4d 3d ed ff ff 40 a0 7c 4d 3d ed ff ff ..|M=...@.|M=...
80 a0 7c 4d 3d ed ff ff c0 a0 7c 4d 3d ed ff ff ..|M=.....|M=...
backtrace:
[<00000000f4b5cfe2>] __kmalloc+0x1a8/0x3e0
[<0000000028665e7f>] io_ctl_init+0xa7/0x120 [btrfs]
[<00000000a1f95b2d>] __btrfs_write_out_cache+0x86/0x4a0 [btrfs]
[<00000000207ea1b0>] btrfs_write_out_cache+0x7f/0xf0 [btrfs]
[<00000000af21f534>] btrfs_start_dirty_block_groups+0x27b/0x580 [btrfs]
[<00000000c3c23d44>] btrfs_commit_transaction+0xa6f/0xe70 [btrfs]
[<000000009588930c>] create_subvol+0x581/0x9a0 [btrfs]
[<000000009ef2fd7f>] btrfs_mksubvol+0x3fb/0x4a0 [btrfs]
[<00000000474e5187>] __btrfs_ioctl_snap_create+0x119/0x1a0 [btrfs]
[<00000000708ee349>] btrfs_ioctl_snap_create_v2+0xb0/0xf0 [btrfs]
[<00000000ea60106f>] btrfs_ioctl+0x12c/0x3130 [btrfs]
[<000000005c923d6d>] __x64_sys_ioctl+0x83/0xb0
[<0000000043ace2c9>] do_syscall_64+0x33/0x80
[<00000000904efbce>] entry_SYSCALL_64_after_hwframe+0x44/0xa9--- fs/btrfs/disk-io.c | 1 + fs/btrfs/free-space-cache.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-)
fs/btrfs/disk-io.c +1 -0
@@ -4574,6 +4574,7 @@ static void btrfs_cleanup_bg_io(struct b cache->io_ctl.inode =NULL ;iput (inode); } +ASSERT (cache->io_ctl.pages ==NULL );btrfs_put_block_group (cache); }
fs/btrfs/free-space-cache.c +1 -1
@@ -1186,7 +1186,6 @@ static int __btrfs_wait_cache_io(struct ret =update_cache_item (trans, root, inode, path, offset, io_ctl->entries, io_ctl->bitmaps); out: -io_ctl_free (io_ctl);if (ret) {invalidate_inode_pages2 (inode->i_mapping);BTRFS_I (inode)->generation =0 ;
@@ -1346,6 +1345,7 @@ static int __btrfs_write_out_cache(struc* them out later */ io_ctl_drop_pages (io_ctl); +io_ctl_free (io_ctl);unlock_extent_cached (&BTRFS_I (inode)->io_tree,0 ,i_size_read (inode) -1 , &cached_state);
Greg Kroah-Hartman
maintainerPATCH 175/255 btrfs: detect nocow for swap after snapshot delete
In reply to Greg Kroah-HartmanFrom: Boris Burkov <[email protected]>
commit a84d5d429f9eb56f81b388609841ed993f0ddfca upstream.
can_nocow_extent and btrfs_cross_ref_exist both rely on a heuristic for detecting a must cow condition which is not exactly accurate, but saves unnecessary tree traversal. The incorrect assumption is that if the extent was created in a generation smaller than the last snapshot generation, it must be referenced by that snapshot. That is true, except the snapshot could have since been deleted, without affecting the last snapshot generation.
The original patch claimed a performance win from this check, but it also leads to a bug where you are unable to use a swapfile if you ever snapshotted the subvolume it's in. Make the check slower and more strict for the swapon case, without modifying the general cow checks as a compromise. Turning swap on does not seem to be a particularly performance sensitive operation, so incurring a possibly unnecessary btrfs_search_slot seems worthwhile for the added usability.
Note: Until the snapshot is competely cleaned after deletion, check_committed_refs will still cause the logic to think that cow is necessary, so the user must until 'btrfs subvolu sync' finished before activating the swapfile swapon.
--- fs/btrfs/ctree.h | 4 ++-- fs/btrfs/extent-tree.c | 17 +++++++++++------ fs/btrfs/file.c | 2 +- fs/btrfs/inode.c | 16 +++++++++------- 4 files changed, 23 insertions(+), 16 deletions(-)
fs/btrfs/ctree.h +2 -2
@@ -2468,7 +2468,7 @@ int btrfs_pin_extent_for_log_replay(stru u64 bytenr, u64 num_bytes);int btrfs_exclude_logged_extents (struct extent_buffer *eb);int btrfs_cross_ref_exist (struct btrfs_root *root, -u64 objectid,u64 offset,u64 bytenr); +u64 objectid,u64 offset,u64 bytenr,bool strict); struct extent_buffer *btrfs_alloc_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, u64 parent, u64 root_objectid,
@@ -2854,7 +2854,7 @@ struct extent_map *btrfs_get_extent_fiem u64 start, u64 len); noinline int can_nocow_extent(struct inode *inode, u64 offset, u64 *len,u64 *orig_start,u64 *orig_block_len, -u64 *ram_bytes); +u64 *ram_bytes,bool strict);void __btrfs_del_delalloc_inode (struct btrfs_root *root,struct btrfs_inode *inode);
fs/btrfs/extent-tree.c +11 -6
@@ -2306,7 +2306,8 @@ static noinline int check_delayed_ref(st static noinline int check_committed_ref(struct btrfs_root *root,struct btrfs_path *path, -u64 objectid,u64 offset,u64 bytenr) +u64 objectid,u64 offset,u64 bytenr, +bool strict) {struct btrfs_fs_info *fs_info = root->fs_info;struct btrfs_root *extent_root = fs_info->extent_root;
@@ -2348,9 +2349,13 @@ static noinline int check_committed_ref( btrfs_extent_inline_ref_size(BTRFS_EXTENT_DATA_REF_KEY)) goto out; -/* If extent created before last snapshot => it's definitely shared */ -if (btrfs_extent_generation (leaf, ei) <= -btrfs_root_last_snapshot (&root->root_item)) +/* +* If extent created before last snapshot => it's shared unless the +* snapshot has been deleted. Use the heuristic if strict is false. +*/ +if (!strict && + (btrfs_extent_generation (leaf, ei) <= +btrfs_root_last_snapshot (&root->root_item))) goto out; iref = (struct btrfs_extent_inline_ref *)(ei +1 );
@@ -2375,7 +2380,7 @@ out: }int btrfs_cross_ref_exist (struct btrfs_root *root,u64 objectid,u64 offset, -u64 bytenr) +u64 bytenr,bool strict) {struct btrfs_path *path;int ret;
@@ -2386,7 +2391,7 @@ int btrfs_cross_ref_exist(struct btrfs_r do { ret = check_committed_ref(root, path, objectid, - offset, bytenr); + offset, bytenr, strict); if (ret && ret != -ENOENT) goto out;
fs/btrfs/file.c +1 -1
@@ -1568,7 +1568,7 @@ int btrfs_check_can_nocow(struct btrfs_i } ret =can_nocow_extent (&inode->vfs_inode, lockstart, &num_bytes, -NULL ,NULL ,NULL ); +NULL ,NULL ,NULL , false);if (ret <=0 ) { ret =0 ;if (!nowait)
fs/btrfs/inode.c +9 -7
@@ -1611,7 +1611,7 @@ next_slot: goto out_check; ret =btrfs_cross_ref_exist (root, ino, found_key.offset - - extent_offset, disk_bytenr); + extent_offset, disk_bytenr, false);if (ret) {/* * ret could be -EIO if the above fails to read
@@ -6957,7 +6957,7 @@ static struct extent_map *btrfs_new_exte*/ noinline int can_nocow_extent(struct inode *inode, u64 offset, u64 *len,u64 *orig_start,u64 *orig_block_len, -u64 *ram_bytes) +u64 *ram_bytes,bool strict) {struct btrfs_fs_info *fs_info =btrfs_sb (inode->i_sb);struct btrfs_path *path;
@@ -7035,8 +7035,9 @@ noinline int can_nocow_extent(struct ino* Do the same check as in btrfs_cross_ref_exist but without the * unnecessary search. */ -if (btrfs_file_extent_generation (leaf, fi) <= -btrfs_root_last_snapshot (&root->root_item)) +if (!strict && + (btrfs_file_extent_generation (leaf, fi) <= +btrfs_root_last_snapshot (&root->root_item))) goto out; backref_offset =btrfs_file_extent_offset (leaf, fi);
@@ -7072,7 +7073,8 @@ noinline int can_nocow_extent(struct ino*/ ret =btrfs_cross_ref_exist (root,btrfs_ino (BTRFS_I (inode)), - key.offset - backref_offset, disk_bytenr); + key.offset - backref_offset, disk_bytenr, + strict);if (ret) { ret =0 ; goto out;
@@ -7293,7 +7295,7 @@ static int btrfs_get_blocks_direct_write block_start = em->block_start + (start - em->start);if (can_nocow_extent (inode, start, &len, &orig_start, - &orig_block_len, &ram_bytes) ==1 && + &orig_block_len, &ram_bytes, false) ==1 &&btrfs_inc_nocow_writers (fs_info, block_start)) {struct extent_map *em2;
@@ -10103,7 +10105,7 @@ static int btrfs_swap_activate(struct swfree_extent_map (em); em =NULL ; - ret =can_nocow_extent (inode, start, &len,NULL ,NULL ,NULL ); + ret =can_nocow_extent (inode, start, &len,NULL ,NULL ,NULL , true);if (ret <0 ) { goto out; }else if (ret) {
Greg Kroah-Hartman
maintainerPATCH 176/255 fbcon: prevent user font height or width change from causing potential out-of-bounds access
In reply to Greg Kroah-HartmanFrom: George Kennedy <[email protected]>
commit 39b3cffb8cf3111738ea993e2757ab382253d86a upstream.
Add a check to fbcon_resize() to ensure that a possible change to user font height or user font width will not allow a font data out-of-bounds access.
NOTE: must use original charcount in calculation as font charcount can change and cannot be used to determine the font data allocated size.
--- drivers/video/fbdev/core/fbcon.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-)
drivers/video/fbdev/core/fbcon.c +23 -2
@@ -2191,6 +2191,9 @@ static void updatescrollmode(struct fbco } } +#define PITCH (w) (((w) + 7) >> 3) +#define CALC_FONTSZ (h, p, c) ((h) * (p) * (c))/* size = height * pitch * charcount */ +static int fbcon_resize (struct vc_data *vc,unsigned int width,unsigned int height,unsigned int user) {
@@ -2200,6 +2203,24 @@ static int fbcon_resize(struct vc_data *struct fb_var_screeninfo var = info->var;int x_diff, y_diff, virt_w, virt_h, virt_fw, virt_fh; +if (ops->p && ops->p->userfont &&FNTSIZE (vc->vc_font.data)) { +int size; +int pitch =PITCH (vc->vc_font.width); + +/* +* If user font, ensure that a possible change to user font +* height or width will not allow a font data out-of-bounds access. +* NOTE: must use original charcount in calculation as font +* charcount can change and cannot be used to determine the +* font data allocated size. +*/ +if (pitch <=0 ) +return -EINVAL ; + size =CALC_FONTSZ (vc->vc_font.height, pitch,FNTCHARCNT (vc->vc_font.data)); +if (size >FNTSIZE (vc->vc_font.data)) +return -EINVAL ; + } + virt_w =FBCON_SWAP (ops->rotate, width, height); virt_h =FBCON_SWAP (ops->rotate, height, width); virt_fw = FBCON_SWAP(ops->rotate, vc->vc_font.width,
@@ -2652,7 +2673,7 @@ static int fbcon_set_font(struct vc_dataint size;int i, csum;u8 *new_data, *data = font->data; -int pitch = (font->width+7 ) >>3 ; +int pitch =PITCH (font->width);/* Is there a reason why fbconsole couldn't handle any charcount >256? * If not this check should be changed to charcount < 256 */
@@ -2668,7 +2689,7 @@ static int fbcon_set_font(struct vc_dataif (fbcon_invalid_charcount (info, charcount))return -EINVAL ; - size = h * pitch * charcount; + size =CALC_FONTSZ (h, pitch, charcount); new_data =kmalloc (FONT_EXTRA_WORDS *sizeof (int ) + size,GFP_USER );
Greg Kroah-Hartman
maintainerPATCH 177/255 USB: lvtest: return proper error code in probe
In reply to Greg Kroah-HartmanFrom: Evgeny Novikov <[email protected]>
commit 531412492ce93ea29b9ca3b4eb5e3ed771f851dd upstream.
lvs_rh_probe() can return some nonnegative value from usb_control_msg() when it is less than "USB_DT_HUB_NONVAR_SIZE + 2" that is considered as a failure. Make lvs_rh_probe() return -EINVAL in this case.
Found by Linux Driver Verification project (linuxtesting.org).
--- drivers/usb/misc/lvstest.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/usb/misc/lvstest.c +1 -1
@@ -426,7 +426,7 @@ static int lvs_rh_probe(struct usb_inter USB_DT_SS_HUB_SIZE, USB_CTRL_GET_TIMEOUT);if (ret < (USB_DT_HUB_NONVAR_SIZE +2 )) {dev_err (&hdev->dev,"wrong root hub descriptor read %d\n" , ret); -return ret; +return ret <0 ? ret : -EINVAL ; }/* submit urb to poll interrupt endpoint */
Greg Kroah-Hartman
maintainerPATCH 178/255 vt: defer kfree() of vc_screenbuf in vc_do_resize()
In reply to Greg Kroah-HartmanFrom: Tetsuo Handa <[email protected]>
commit f8d1653daec02315e06d30246cff4af72e76e54e upstream.
syzbot is reporting UAF bug in set_origin() from vc_do_resize() [1], for vc_do_resize() calls kfree(vc->vc_screenbuf) before calling set_origin().
Unfortunately, in set_origin(), vc->vc_sw->con_set_origin() might access vc->vc_pos when scroll is involved in order to manipulate cursor, but vc->vc_pos refers already released vc->vc_screenbuf until vc->vc_pos gets updated based on the result of vc->vc_sw->con_set_origin().
Preserving old buffer and tolerating outdated vc members until set_origin() completes would be easier than preventing vc->vc_sw->con_set_origin() from accessing outdated vc members.
[1] https://syzkaller.appspot.com/bug?id=6649da2081e2ebdc65c0642c214b27fe91099db3
--- drivers/tty/vt/vt.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/tty/vt/vt.c +3 -2
@@ -1196,7 +1196,7 @@ static int vc_do_resize(struct tty_strucunsigned int old_rows, old_row_size, first_copied_row;unsigned int new_cols, new_rows, new_row_size, new_screen_size;unsigned int user; -unsigned short *newscreen; +unsigned short *oldscreen, *newscreen;struct uni_screen *new_uniscr =NULL ;WARN_CONSOLE_UNLOCKED ();
@@ -1294,10 +1294,11 @@ static int vc_do_resize(struct tty_strucif (new_scr_end > new_origin)scr_memsetw ((void *)new_origin, vc->vc_video_erase_char, new_scr_end - new_origin); -kfree (vc->vc_screenbuf); + oldscreen = vc->vc_screenbuf; vc->vc_screenbuf = newscreen; vc->vc_screenbuf_size = new_screen_size;set_origin (vc); +kfree (oldscreen);/* do part of a reset_terminal() */ vc->vc_top =0 ;
Greg Kroah-Hartman
maintainerPATCH 179/255 vt_ioctl: change VT_RESIZEX ioctl to check for error return from vc_resize()
In reply to Greg Kroah-HartmanFrom: George Kennedy <[email protected]>
commit bc5269ca765057a1b762e79a1cfd267cd7bf1c46 upstream.
vc_resize() can return with an error after failure. Change VT_RESIZEX ioctl to save struct vc_data values that are modified and restore the original values in case of error.
--- drivers/tty/vt/vt_ioctl.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)
drivers/tty/vt/vt_ioctl.c +11 -1
@@ -893,12 +893,22 @@ int vt_ioctl(struct tty_struct *tty,console_lock (); vcp = vc_cons[i].d;if (vcp) { +int ret; +int save_scan_lines = vcp->vc_scan_lines; +int save_font_height = vcp->vc_font.height; +if (v.v_vlin) vcp->vc_scan_lines = v.v_vlin;if (v.v_clin) vcp->vc_font.height = v.v_clin; vcp->vc_resize_user =1 ; -vc_resize (vcp, v.v_cols, v.v_rows); + ret =vc_resize (vcp, v.v_cols, v.v_rows); +if (ret) { + vcp->vc_scan_lines = save_scan_lines; + vcp->vc_font.height = save_font_height; +console_unlock (); +return ret; + } }console_unlock (); }
Greg Kroah-Hartman
maintainerPATCH 180/255 serial: samsung: Removes the IRQ not found warning
In reply to Greg Kroah-HartmanFrom: Tamseel Shams <[email protected]>
commit 8c6c378b0cbe0c9f1390986b5f8ffb5f6ff7593b upstream.
In few older Samsung SoCs like s3c2410, s3c2412 and s3c2440, UART IP is having 2 interrupt lines. However, in other SoCs like s3c6400, s5pv210, exynos5433, and exynos4210 UART is having only 1 interrupt line. Due to this, "platform_get_irq(platdev, 1)" call in the driver gives the following false-positive error:
"IRQ index 1 not found" on newer SoC's.
This patch adds the condition to check for Tx interrupt only for the those SoC's which have 2 interrupt lines.
--- drivers/tty/serial/samsung_tty.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
drivers/tty/serial/samsung_tty.c +5 -3
@@ -1911,9 +1911,11 @@ static int s3c24xx_serial_init_port(stru ourport->tx_irq = ret +1 ; } - ret =platform_get_irq (platdev,1 ); -if (ret >0 ) - ourport->tx_irq = ret; +if (!s3c24xx_serial_has_interrupt_mask (port)) { + ret =platform_get_irq (platdev,1 ); +if (ret >0 ) + ourport->tx_irq = ret; + }/* * DMA is currently supported only on DT platforms, if DMA properties * are specified.
Greg Kroah-Hartman
maintainerPATCH 181/255 serial: pl011: Fix oops on -EPROBE_DEFER
In reply to Greg Kroah-HartmanFrom: Lukas Wunner <[email protected]>
commit 27afac93e3bd7fa89749cf11da5d86ac9cde4dba upstream.
If probing of a pl011 gets deferred until after free_initmem(), an oops ensues because pl011_console_match() is called which has been freed.
Fix by removing the __init attribute from the function and those it calls.
Commit 10879ae5f12e ("serial: pl011: add console matching function") introduced pl011_console_match() not just for early consoles but regular preferred consoles, such as those added by acpi_parse_spcr(). Regular consoles may be registered after free_initmem() for various reasons, one being deferred probing, another being dynamic enablement of serial ports using a DeviceTree overlay.
Thus, pl011_console_match() must not be declared __init and the functions it calls mustn't either.
Stack trace for posterity:
Unable to handle kernel paging request at virtual address 80c38b58 Internal error: Oops: 8000000d [#1] PREEMPT SMP ARM PC is at pl011_console_match+0x0/0xfc LR is at register_console+0x150/0x468
[<80187004>] (register_console)
[<805a8184>] (uart_add_one_port)
[<805b2b68>] (pl011_register_port)
[<805b3ce4>] (pl011_probe)
[<80569214>] (amba_probe)
[<805ca088>] (really_probe)
[<805ca2ec>] (driver_probe_device)
[<805ca5b0>] (__device_attach_driver)
[<805c8060>] (bus_for_each_drv)
[<805c9dfc>] (__device_attach)
[<805ca630>] (device_initial_probe)
[<805c90a8>] (bus_probe_device)
[<805c95a8>] (deferred_probe_work_func)
--- drivers/tty/serial/amba-pl011.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-)
drivers/tty/serial/amba-pl011.c +5 -6
@@ -2241,9 +2241,8 @@ pl011_console_write(struct console *co,clk_disable (uap->clk); } -static void __init -pl011_console_get_options (struct uart_amba_port *uap,int *baud, -int *parity,int *bits) +static void pl011_console_get_options (struct uart_amba_port *uap,int *baud, +int *parity,int *bits) {if (pl011_read (uap,REG_CR ) & UART01x_CR_UARTEN) {unsigned int lcr_h, ibrd, fbrd;
@@ -2276,7 +2275,7 @@ pl011_console_get_options(struct uart_am } } -static int __init pl011_console_setup (struct console *co,char *options) +static int pl011_console_setup (struct console *co,char *options) {struct uart_amba_port *uap;int baud =38400 ;
@@ -2344,8 +2343,8 @@ static int __init pl011_console_setup(st* * Returns 0 if console matches; otherwise non-zero to use default matching */ -static int __init pl011_console_match (struct console *co,char *name,int idx, -char *options) +static int pl011_console_match (struct console *co,char *name,int idx, +char *options) {unsigned char iotype;resource_size_t addr;
Greg Kroah-Hartman
maintainerPATCH 182/255 serial: pl011: Dont leak amba_ports entry on driver register error
In reply to Greg Kroah-HartmanFrom: Lukas Wunner <[email protected]>
commit 89efbe70b27dd325d8a8c177743a26b885f7faec upstream.
pl011_probe() calls pl011_setup_port() to reserve an amba_ports[] entry, then calls pl011_register_port() to register the uart driver with the tty layer.
If registration of the uart driver fails, the amba_ports[] entry is not released. If this happens 14 times (value of UART_NR macro), then all amba_ports[] entries will have been leaked and driver probing is no longer possible. (To be fair, that can only happen if the DeviceTree doesn't contain alias IDs since they cause the same entry to be used for
a given port.) Fix it.
--- drivers/tty/serial/amba-pl011.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/tty/serial/amba-pl011.c +4 -1
@@ -2615,7 +2615,7 @@ static int pl011_setup_port(struct devicstatic int pl011_register_port (struct uart_amba_port *uap) { -int ret; +int ret, i;/* Ensure interrupts from this UART are masked and cleared */ pl011_write (0 , uap,REG_IMSC );
@@ -2626,6 +2626,9 @@ static int pl011_register_port(struct uaif (ret <0 ) {dev_err (uap->port.dev,"Failed to register AMBA-PL011 driver\n" ); +for (i =0 ; i <ARRAY_SIZE (amba_ports); i++) +if (amba_ports[i] == uap) + amba_ports[i] =NULL ;return ret; } }
Greg Kroah-Hartman
maintainerPATCH 183/255 serial: stm32: avoid kernel warning on absence of optional IRQ
In reply to Greg Kroah-HartmanFrom: Holger Assmann <[email protected]>
commit fdf16d78941b4f380753053d229955baddd00712 upstream.
stm32_init_port() of the stm32-usart may trigger a warning in platform_get_irq() when the device tree specifies no wakeup interrupt.
The wakeup interrupt is usually a board-specific GPIO and the driver functions correctly in its absence. The mainline stm32mp151.dtsi does not specify it, so all mainline device trees trigger an unnecessary kernel warning. Use of platform_get_irq_optional() avoids this.
--- drivers/tty/serial/stm32-usart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/tty/serial/stm32-usart.c +1 -1
@@ -962,7 +962,7 @@ static int stm32_init_port(struct stm32_return ret;if (stm32port->info->cfg.has_wakeup) { - stm32port->wakeirq =platform_get_irq (pdev,1 ); + stm32port->wakeirq =platform_get_irq_optional (pdev,1 );if (stm32port->wakeirq <=0 && stm32port->wakeirq != -ENXIO )return stm32port->wakeirq ? : -ENODEV ; }
Greg Kroah-Hartman
maintainerPATCH 184/255 serial: 8250_exar: Fix number of ports for Commtech PCIe cards
In reply to Greg Kroah-HartmanFrom: Valmer Huhn <[email protected]>
commit c6b9e95dde7b54e6a53c47241201ab5a4035c320 upstream.
The following in 8250_exar.c line 589 is used to determine the number of ports for each Exar board:
nr_ports = board->num_ports ? board->num_ports : pcidev->device & 0x0f;
If the number of ports a card has is not explicitly specified, it defaults to the rightmost 4 bits of the PCI device ID. This is prone to error since not all PCI device IDs contain a number which corresponds to the number of ports that card provides.
This particular case involves COMMTECH_4222PCIE, COMMTECH_4224PCIE and COMMTECH_4228PCIE cards with device IDs 0x0022, 0x0020 and 0x0021. Currently the multiport cards receive 2, 0 and 1 port instead of 2, 4 and 8 ports respectively.
To fix this, each Commtech Fastcom PCIe card is given a struct where the number of ports is explicitly specified. This ensures 'board->num_ports' is used instead of the default 'pcidev->device & 0x0f'.
--- drivers/tty/serial/8250/8250_exar.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-)
drivers/tty/serial/8250/8250_exar.c +21 -3
@@ -744,6 +744,24 @@ static const struct exar8250_board pbn_e .exit = pci_xr17v35x_exit, }; +static const struct exar8250_board pbn_fastcom35x_2 = { + .num_ports =2 , + .setup = pci_xr17v35x_setup, + .exit = pci_xr17v35x_exit, +}; + +static const struct exar8250_board pbn_fastcom35x_4 = { + .num_ports =4 , + .setup = pci_xr17v35x_setup, + .exit = pci_xr17v35x_exit, +}; + +static const struct exar8250_board pbn_fastcom35x_8 = { + .num_ports =8 , + .setup = pci_xr17v35x_setup, + .exit = pci_xr17v35x_exit, +}; +static const struct exar8250_board pbn_exar_XR17V4358 = { .num_ports =12 , .setup = pci_xr17v35x_setup,
@@ -811,9 +829,9 @@ static const struct pci_device_id exar_pEXAR_DEVICE (EXAR ,XR17V358 , pbn_exar_XR17V35x),EXAR_DEVICE (EXAR ,XR17V4358 , pbn_exar_XR17V4358),EXAR_DEVICE (EXAR ,XR17V8358 , pbn_exar_XR17V8358), - EXAR_DEVICE(COMMTECH, 4222PCIE, pbn_exar_XR17V35x), - EXAR_DEVICE(COMMTECH, 4224PCIE, pbn_exar_XR17V35x), - EXAR_DEVICE(COMMTECH, 4228PCIE, pbn_exar_XR17V35x), + EXAR_DEVICE(COMMTECH, 4222PCIE, pbn_fastcom35x_2), + EXAR_DEVICE(COMMTECH, 4224PCIE, pbn_fastcom35x_4), + EXAR_DEVICE(COMMTECH, 4228PCIE, pbn_fastcom35x_8), EXAR_DEVICE(COMMTECH, 4222PCI335, pbn_fastcom335_2), EXAR_DEVICE(COMMTECH, 4224PCI335, pbn_fastcom335_4),
Greg Kroah-Hartman
maintainerPATCH 185/255 serial: 8250: change lock order in serial8250_do_startup()
In reply to Greg Kroah-HartmanFrom: Sergey Senozhatsky <[email protected]>
commit 205d300aea75623e1ae4aa43e0d265ab9cf195fd upstream.
We have a number of "uart.port->desc.lock vs desc.lock->uart.port" lockdep reports coming from 8250 driver; this causes a bit of trouble to people, so let's fix it.
The problem is reverse lock order in two different call paths:
chain #1:
serial8250_do_startup()
spin_lock_irqsave(&port->lock);
disable_irq_nosync(port->irq);
raw_spin_lock_irqsave(&desc->lock)chain #2:
__report_bad_irq()
raw_spin_lock_irqsave(&desc->lock)
for_each_action_of_desc()
printk()
spin_lock_irqsave(&port->lock);Fix this by changing the order of locks in serial8250_do_startup():
do disable_irq_nosync() first, which grabs desc->lock, and grab uart->port after that, so that chain #1 and chain #2 have same lock order.
Full lockdep splat:
======================================================
WARNING: possible circular locking dependency detected 5.4.39 #55 Not tainted
======================================================
swapper/0/0 is trying to acquire lock:
ffffffffab65b6c0 (console_owner){-...}, at: console_lock_spinning_enable+0x31/0x57
but task is already holding lock:
ffff88810a8e34c0 (&irq_desc_lock_class){-.-.}, at: __report_bad_irq+0x5b/0xba
which lock already depends on the new lock.
the existing dependency chain (in reverse order) is:
-> #2 (&irq_desc_lock_class){-.-.}:
_raw_spin_lock_irqsave+0x61/0x8d
__irq_get_desc_lock+0x65/0x89
__disable_irq_nosync+0x3b/0x93
serial8250_do_startup+0x451/0x75c
uart_startup+0x1b4/0x2ff
uart_port_activate+0x73/0xa0
tty_port_open+0xae/0x10a
uart_open+0x1b/0x26
tty_open+0x24d/0x3a0
chrdev_open+0xd5/0x1cc
do_dentry_open+0x299/0x3c8
path_openat+0x434/0x1100
do_filp_open+0x9b/0x10a
do_sys_open+0x15f/0x3d7
kernel_init_freeable+0x157/0x1dd
kernel_init+0xe/0x105
ret_from_fork+0x27/0x50-> #1 (&port_lock_key){-.-.}:
_raw_spin_lock_irqsave+0x61/0x8d
serial8250_console_write+0xa7/0x2a0
console_unlock+0x3b7/0x528
vprintk_emit+0x111/0x17f
printk+0x59/0x73
register_console+0x336/0x3a4
uart_add_one_port+0x51b/0x5be
serial8250_register_8250_port+0x454/0x55e
dw8250_probe+0x4dc/0x5b9
platform_drv_probe+0x67/0x8b
really_probe+0x14a/0x422
driver_probe_device+0x66/0x130
device_driver_attach+0x42/0x5b
__driver_attach+0xca/0x139
bus_for_each_dev+0x97/0xc9
bus_add_driver+0x12b/0x228
driver_register+0x64/0xed
do_one_initcall+0x20c/0x4a6
do_initcall_level+0xb5/0xc5
do_basic_setup+0x4c/0x58
kernel_init_freeable+0x13f/0x1dd
kernel_init+0xe/0x105
ret_from_fork+0x27/0x50-> #0 (console_owner){-...}:
__lock_acquire+0x118d/0x2714
lock_acquire+0x203/0x258
console_lock_spinning_enable+0x51/0x57
console_unlock+0x25d/0x528
vprintk_emit+0x111/0x17f
printk+0x59/0x73
__report_bad_irq+0xa3/0xba
note_interrupt+0x19a/0x1d6
handle_irq_event_percpu+0x57/0x79
handle_irq_event+0x36/0x55
handle_fasteoi_irq+0xc2/0x18a
do_IRQ+0xb3/0x157
ret_from_intr+0x0/0x1d
cpuidle_enter_state+0x12f/0x1fd
cpuidle_enter+0x2e/0x3d
do_idle+0x1ce/0x2ce
cpu_startup_entry+0x1d/0x1f
start_kernel+0x406/0x46a
secondary_startup_64+0xa4/0xb0other info that might help us debug this:
Chain exists of: console_owner --> &port_lock_key --> &irq_desc_lock_class Possible unsafe locking scenario:
CPU0 CPU1
---- ----
lock(&irq_desc_lock_class);
lock(&port_lock_key);
lock(&irq_desc_lock_class); lock(console_owner);
*** DEADLOCK ***
2 locks held by swapper/0/0:
#0: ffff88810a8e34c0 (&irq_desc_lock_class){-.-.}, at: __report_bad_irq+0x5b/0xba #1: ffffffffab65b5c0 (console_lock){+.+.}, at: console_trylock_spinning+0x20/0x181
stack backtrace: CPU: 0 PID: 0 Comm: swapper/0 Not tainted 5.4.39 #55 Hardware name: XXXXXX Call Trace: <IRQ> dump_stack+0xbf/0x133 ? print_circular_bug+0xd6/0xe9 check_noncircular+0x1b9/0x1c3 __lock_acquire+0x118d/0x2714 lock_acquire+0x203/0x258 ? console_lock_spinning_enable+0x31/0x57 console_lock_spinning_enable+0x51/0x57 ? console_lock_spinning_enable+0x31/0x57 console_unlock+0x25d/0x528 ? console_trylock+0x18/0x4e vprintk_emit+0x111/0x17f ? lock_acquire+0x203/0x258 printk+0x59/0x73 __report_bad_irq+0xa3/0xba note_interrupt+0x19a/0x1d6 handle_irq_event_percpu+0x57/0x79 handle_irq_event+0x36/0x55 handle_fasteoi_irq+0xc2/0x18a do_IRQ+0xb3/0x157 common_interrupt+0xf/0xf </IRQ>
--- drivers/tty/serial/8250/8250_port.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
drivers/tty/serial/8250/8250_port.c +6 -3
@@ -2274,6 +2274,10 @@ int serial8250_do_startup(struct uart_poif (port->irq && !(up->port.flags &UPF_NO_THRE_TEST )) {unsigned char iir1; + +if (port->irqflags &IRQF_SHARED ) +disable_irq_nosync (port->irq); +/* * Test for UARTs that do not reassert THRE when the * transmitter is idle and the interrupt has already
@@ -2283,8 +2287,6 @@ int serial8250_do_startup(struct uart_po* allow register changes to become visible. */ spin_lock_irqsave (&port->lock, flags); -if (up->port.irqflags &IRQF_SHARED ) -disable_irq_nosync (port->irq);wait_for_xmitr (up,UART_LSR_THRE );serial_port_out_sync (port,UART_IER ,UART_IER_THRI );
@@ -2296,9 +2298,10 @@ int serial8250_do_startup(struct uart_po iir =serial_port_in (port,UART_IIR );serial_port_out (port,UART_IER ,0 ); +spin_unlock_irqrestore (&port->lock, flags); +if (port->irqflags &IRQF_SHARED )enable_irq (port->irq); -spin_unlock_irqrestore (&port->lock, flags);/* * If the interrupt is not reasserted, or we otherwise
Greg Kroah-Hartman
maintainerPATCH 186/255 io_uring: clear req->result on IOPOLL re-issue
In reply to Greg Kroah-HartmanFrom: Jens Axboe <[email protected]>
commit 56450c20fe10d4d93f58019109aa4e06fc0b9206 upstream.
Make sure we clear req->result, which was set to -EAGAIN for retry purposes, when moving it to the reissue list. Otherwise we can end up retrying a request more than once, which leads to weird results in the io-wq handling (and other spots).
--- fs/io_uring.c | 1 + 1 file changed, 1 insertion(+)
fs/io_uring.c +1 -0
@@ -1810,6 +1810,7 @@ static void io_iopoll_complete(struct io req = list_first_entry(done, struct io_kiocb, list);if (READ_ONCE (req->result) == -EAGAIN ) { + req->result =0 ; req->iopoll_completed =0 ;list_move_tail (&req->list, &again);continue ;
Greg Kroah-Hartman
maintainerPATCH 187/255 writeback: Protect inode->i_io_list with inode->i_lock
In reply to Greg Kroah-HartmanFrom: Jan Kara <[email protected]>
commit b35250c0816c7cf7d0a8de92f5fafb6a7508a708 upstream.
Currently, operations on inode->i_io_list are protected by wb->list_lock. In the following patches we'll need to maintain consistency between inode->i_state and inode->i_io_list so change the code so that inode->i_lock protects also all inode's i_io_list handling.
--- fs/fs-writeback.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-)
fs/fs-writeback.c +17 -5
@@ -144,6 +144,7 @@ static void inode_io_list_del_locked(str struct bdi_writeback *wb) {assert_spin_locked (&wb->list_lock); +assert_spin_locked (&inode->i_lock);list_del_init (&inode->i_io_list);wb_io_lists_depopulated (wb);
@@ -1122,7 +1123,9 @@ void inode_io_list_del(struct inode *inostruct bdi_writeback *wb; wb =inode_to_wb_and_lock_list (inode); +spin_lock (&inode->i_lock);inode_io_list_del_locked (inode, wb); +spin_unlock (&inode->i_lock);spin_unlock (&wb->list_lock); }EXPORT_SYMBOL (inode_io_list_del);
@@ -1172,8 +1175,10 @@ void sb_clear_inode_writeback(struct ino* the case then the inode must have been redirtied while it was being written * out and we don't reset its dirtied_when. */ -static void redirty_tail (struct inode *inode,struct bdi_writeback *wb) +static void redirty_tail_locked (struct inode *inode,struct bdi_writeback *wb) { +assert_spin_locked (&inode->i_lock); +if (!list_empty (&wb->b_dirty)) {struct inode *tail;
@@ -1184,6 +1189,13 @@ static void redirty_tail(struct inode *iinode_io_list_move_locked (inode, wb, &wb->b_dirty); } +static void redirty_tail (struct inode *inode,struct bdi_writeback *wb) +{ +spin_lock (&inode->i_lock); +redirty_tail_locked (inode, wb); +spin_unlock (&inode->i_lock); +} +/* * requeue inode for re-scanning after bdi->b_io list is exhausted. */
@@ -1394,7 +1406,7 @@ static void requeue_inode(struct inode ** writeback is not making progress due to locked * buffers. Skip this inode for now. */ -redirty_tail (inode, wb); +redirty_tail_locked (inode, wb);return ; }
@@ -1414,7 +1426,7 @@ static void requeue_inode(struct inode ** retrying writeback of the dirty page/inode * that cannot be performed immediately. */ -redirty_tail (inode, wb); +redirty_tail_locked (inode, wb); } }else if (inode->i_state &I_DIRTY ) {/*
@@ -1422,7 +1434,7 @@ static void requeue_inode(struct inode ** such as delayed allocation during submission or metadata * updates after data IO completion. */ -redirty_tail (inode, wb); +redirty_tail_locked (inode, wb); }else if (inode->i_state &I_DIRTY_TIME ) { inode->dirtied_when = jiffies;inode_io_list_move_locked (inode, wb, &wb->b_dirty_time);
@@ -1669,8 +1681,8 @@ static long writeback_sb_inodes(struct s*/ spin_lock (&inode->i_lock);if (inode->i_state & (I_NEW |I_FREEING |I_WILL_FREE )) { +redirty_tail_locked (inode, wb);spin_unlock (&inode->i_lock); -redirty_tail (inode, wb);continue ; }if ((inode->i_state &I_SYNC ) && wbc.sync_mode !=WB_SYNC_ALL ) {
Greg Kroah-Hartman
maintainerPATCH 188/255 writeback: Avoid skipping inode writeback
In reply to Greg Kroah-HartmanFrom: Jan Kara <[email protected]>
commit 5afced3bf28100d81fb2fe7e98918632a08feaf5 upstream.
Inode's i_io_list list head is used to attach inode to several different lists - wb->{b_dirty, b_dirty_time, b_io, b_more_io}. When flush worker prepares a list of inodes to writeback e.g. for sync(2), it moves inodes to b_io list. Thus it is critical for sync(2) data integrity guarantees that inode is not requeued to any other writeback list when inode is queued for processing by flush worker. That's the reason why writeback_single_inode() does not touch i_io_list (unless the inode is completely clean) and why __mark_inode_dirty() does not touch i_io_list if I_SYNC flag is set.
However there are two flaws in the current logic:
1) When inode has only I_DIRTY_TIME set but it is already queued in b_io list due to sync(2), concurrent __mark_inode_dirty(inode, I_DIRTY_SYNC) can still move inode back to b_dirty list resulting in skipping writeback of inode time stamps during sync(2).
2) When inode is on b_dirty_time list and writeback_single_inode() races with __mark_inode_dirty() like:
writeback_single_inode() __mark_inode_dirty(inode, I_DIRTY_PAGES)
inode->i_state |= I_SYNC
__writeback_single_inode()
inode->i_state |= I_DIRTY_PAGES; if (inode->i_state & I_SYNC) bail
if (!(inode->i_state & I_DIRTY_ALL))
- not true so nothing done
We end up with I_DIRTY_PAGES inode on b_dirty_time list and thus standard background writeback will not writeback this inode leading to possible dirty throttling stalls etc. (thanks to Martijn Coenen for this analysis).
Fix these problems by tracking whether inode is queued in b_io or b_more_io lists in a new I_SYNC_QUEUED flag. When this flag is set, we know flush worker has queued inode and we should not touch i_io_list. On the other hand we also know that once flush worker is done with the inode it will requeue the inode to appropriate dirty list. When I_SYNC_QUEUED is not set, __mark_inode_dirty() can (and must) move inode to appropriate dirty list.
--- fs/fs-writeback.c | 17 ++++++++++++----- include/linux/fs.h | 8 ++++++-- 2 files changed, 18 insertions(+), 7 deletions(-)
fs/fs-writeback.c +12 -5
@@ -146,6 +146,7 @@ static void inode_io_list_del_locked(strassert_spin_locked (&wb->list_lock);assert_spin_locked (&inode->i_lock); + inode->i_state &= ~I_SYNC_QUEUED ;list_del_init (&inode->i_io_list);wb_io_lists_depopulated (wb); }
@@ -1187,6 +1188,7 @@ static void redirty_tail_locked(struct i inode->dirtied_when = jiffies; }inode_io_list_move_locked (inode, wb, &wb->b_dirty); + inode->i_state &= ~I_SYNC_QUEUED ; }static void redirty_tail (struct inode *inode,struct bdi_writeback *wb)
@@ -1262,8 +1264,11 @@ static int move_expired_inodes(struct libreak ;list_move (&inode->i_io_list, &tmp); moved++; +spin_lock (&inode->i_lock);if (flags &EXPIRE_DIRTY_ATIME ) -set_bit (__I_DIRTY_TIME_EXPIRED, &inode->i_state); + inode->i_state |=I_DIRTY_TIME_EXPIRED ; + inode->i_state |=I_SYNC_QUEUED ; +spin_unlock (&inode->i_lock);if (sb_is_blkdev_sb (inode->i_sb))continue ;if (sb && sb != inode->i_sb)
@@ -1438,6 +1443,7 @@ static void requeue_inode(struct inode * }else if (inode->i_state &I_DIRTY_TIME ) { inode->dirtied_when = jiffies;inode_io_list_move_locked (inode, wb, &wb->b_dirty_time); + inode->i_state &= ~I_SYNC_QUEUED ; }else {/* The inode is clean. Remove from writeback lists. */ inode_io_list_del_locked (inode, wb);
@@ -2301,11 +2307,12 @@ void __mark_inode_dirty(struct inode *in inode->i_state |= flags;/* -* If the inode is being synced, just update its dirty state. -* The unlocker will place the inode on the appropriate -* superblock list, based upon its state. +* If the inode is queued for writeback by flush worker, just +* update its dirty state. Once the flush worker is done with +* the inode it will place it on the appropriate superblock +* list, based upon its state. */ -if (inode->i_state &I_SYNC ) +if (inode->i_state &I_SYNC_QUEUED ) goto out_unlock_inode;/*
include/linux/fs.h +6 -2
@@ -2168,6 +2168,10 @@ static inline void kiocb_clone(struct ki* * I_DONTCACHE Evict inode as soon as it is not used anymore. * +* I_SYNC_QUEUED Inode is queued in b_io or b_more_io writeback lists. +* Used to detect that mark_inode_dirty() should not move +* inode between dirty lists. +* * Q: What is the difference between I_WILL_FREE and I_FREEING? */ #define I_DIRTY_SYNC (1 << 0)
@@ -2185,12 +2189,12 @@ static inline void kiocb_clone(struct ki#define I_DIO_WAKEUP (1 << __I_DIO_WAKEUP)#define I_LINKABLE (1 << 10)#define I_DIRTY_TIME (1 << 11) -#define __I_DIRTY_TIME_EXPIRED 12 -#define I_DIRTY_TIME_EXPIRED (1 << __I_DIRTY_TIME_EXPIRED) +#define I_DIRTY_TIME_EXPIRED (1 << 12)#define I_WB_SWITCH (1 << 13)#define I_OVL_INUSE (1 << 14)#define I_CREATING (1 << 15)#define I_DONTCACHE (1 << 16) +#define I_SYNC_QUEUED (1 << 17)#define I_DIRTY_INODE (I_DIRTY_SYNC | I_DIRTY_DATASYNC)#define I_DIRTY (I_DIRTY_INODE | I_DIRTY_PAGES)
Greg Kroah-Hartman
maintainerPATCH 189/255 writeback: Fix sync livelock due to b_dirty_time processing
In reply to Greg Kroah-HartmanFrom: Jan Kara <[email protected]>
commit f9cae926f35e8230330f28c7b743ad088611a8de upstream.
When we are processing writeback for sync(2), move_expired_inodes() didn't set any inode expiry value (older_than_this). This can result in writeback never completing if there's steady stream of inodes added to b_dirty_time list as writeback rechecks dirty lists after each writeback round whether there's more work to be done. Fix the problem by using sync(2) start time is inode expiry value when processing b_dirty_time list similarly as for ordinarily dirtied inodes. This requires some refactoring of older_than_this handling which simplifies the code noticeably as a bonus.
--- fs/fs-writeback.c | 44 +++++++++++++++------------------------ include/trace/events/writeback.h | 13 +++++------ 2 files changed, 23 insertions(+), 34 deletions(-)
fs/fs-writeback.c +17 -27
@@ -42,7 +42,6 @@struct wb_writeback_work {long nr_pages;struct super_block *sb; -unsigned long *older_than_this;enum writeback_sync_modes sync_mode;unsigned int tagged_writepages:1 ;unsigned int for_kupdate:1 ;
@@ -1234,16 +1233,13 @@ static bool inode_dirtied_after(struct i#define EXPIRE_DIRTY_ATIME 0x0001/* -* Move expired (dirtied before work->older_than_this) dirty inodes from +* Move expired (dirtied before dirtied_before) dirty inodes from * @delaying_queue to @dispatch_queue. */ static int move_expired_inodes (struct list_head *delaying_queue,struct list_head *dispatch_queue, -int flags, -struct wb_writeback_work *work) +int flags,unsigned long dirtied_before) { -unsigned long *older_than_this =NULL ; -unsigned long expire_time;LIST_HEAD (tmp);struct list_head *pos, *node;struct super_block *sb =NULL ;
@@ -1251,16 +1247,9 @@ static int move_expired_inodes(struct liint do_sb_sort =0 ;int moved =0 ; -if ((flags &EXPIRE_DIRTY_ATIME ) ==0 ) - older_than_this = work->older_than_this; -else if (!work->for_sync) { - expire_time = jiffies - (dirtytime_expire_interval *HZ ); - older_than_this = &expire_time; - }while (!list_empty (delaying_queue)) { inode =wb_inode (delaying_queue->prev); -if (older_than_this && -inode_dirtied_after (inode, *older_than_this)) +if (inode_dirtied_after (inode, dirtied_before))break ;list_move (&inode->i_io_list, &tmp); moved++;
@@ -1306,18 +1295,22 @@ out:* | * +--> dequeue for IO */ -static void queue_io (struct bdi_writeback *wb,struct wb_writeback_work *work) +static void queue_io (struct bdi_writeback *wb,struct wb_writeback_work *work, +unsigned long dirtied_before) {int moved; +unsigned long time_expire_jif = dirtied_before;assert_spin_locked (&wb->list_lock);list_splice_init (&wb->b_more_io, &wb->b_io); - moved =move_expired_inodes (&wb->b_dirty, &wb->b_io,0 , work); + moved =move_expired_inodes (&wb->b_dirty, &wb->b_io,0 , dirtied_before); +if (!work->for_sync) + time_expire_jif = jiffies - dirtytime_expire_interval *HZ ; moved +=move_expired_inodes (&wb->b_dirty_time, &wb->b_io, -EXPIRE_DIRTY_ATIME , work); +EXPIRE_DIRTY_ATIME , time_expire_jif);if (moved)wb_io_lists_populated (wb); -trace_writeback_queue_io (wb, work, moved); +trace_writeback_queue_io (wb, work, dirtied_before, moved); }static int write_inode (struct inode *inode,struct writeback_control *wbc)
@@ -1829,7 +1822,7 @@ static long writeback_inodes_wb(struct bblk_start_plug (&plug);spin_lock (&wb->list_lock);if (list_empty (&wb->b_io)) -queue_io (wb, &work); +queue_io (wb, &work, jiffies);__writeback_inodes_wb (wb, &work);spin_unlock (&wb->list_lock);blk_finish_plug (&plug);
@@ -1849,7 +1842,7 @@ static long writeback_inodes_wb(struct b* takes longer than a dirty_writeback_interval interval, then leave a * one-second gap. * -* older_than_this takes precedence over nr_to_write. So we'll only write back +* dirtied_before takes precedence over nr_to_write. So we'll only write back * all dirty pages if they are all attached to "old" mappings. */ static long wb_writeback(struct bdi_writeback *wb,
@@ -1857,14 +1850,11 @@ static long wb_writeback(struct bdi_writ {unsigned long wb_start = jiffies;long nr_pages = work->nr_pages; -unsigned long oldest_jif; +unsigned long dirtied_before = jiffies;struct inode *inode;long progress;struct blk_plug plug; - oldest_jif = jiffies; - work->older_than_this = &oldest_jif; -blk_start_plug (&plug);spin_lock (&wb->list_lock);for (;;) {
@@ -1898,14 +1888,14 @@ static long wb_writeback(struct bdi_writ* safe. */ if (work->for_kupdate) { - oldest_jif = jiffies - + dirtied_before = jiffies -msecs_to_jiffies (dirty_expire_interval *10 ); }else if (work->for_background) - oldest_jif = jiffies; + dirtied_before = jiffies;trace_writeback_start (wb, work);if (list_empty (&wb->b_io)) -queue_io (wb, work); +queue_io (wb, work, dirtied_before);if (work->sb) progress =writeback_sb_inodes (work->sb, wb, work);else
include/trace/events/writeback.h +6 -7
@@ -498,8 +498,9 @@ DEFINE_WBC_EVENT(wbc_writepage); TRACE_EVENT(writeback_queue_io, TP_PROTO(struct bdi_writeback *wb, struct wb_writeback_work *work, + unsigned long dirtied_before, int moved), - TP_ARGS(wb, work, moved), + TP_ARGS(wb, work, dirtied_before, moved), TP_STRUCT__entry( __array(char, name, 32) __field(unsigned long, older)
@@ -509,19 +510,17 @@ TRACE_EVENT(writeback_queue_io,__field (ino_t, cgroup_ino) ),TP_fast_assign ( - unsigned long *older_than_this = work->older_than_this; strscpy_pad(__entry->name, bdi_dev_name(wb->bdi), 32); - __entry->older = older_than_this ? *older_than_this :0 ; - __entry->age = older_than_this ? - (jiffies - *older_than_this) *1000 /HZ :-1 ; + __entry->older = dirtied_before; + __entry->age = (jiffies - dirtied_before) *1000 /HZ ; __entry->moved = moved; __entry->reason = work->reason; __entry->cgroup_ino =__trace_wb_assign_cgroup (wb); ),TP_printk ("bdi %s: older=%lu age=%ld enqueue=%d reason=%s cgroup_ino=%lu" , __entry->name, - __entry->older,/* older_than_this in jiffies */ - __entry->age,/* older_than_this in relative milliseconds */ + __entry->older,/* dirtied_before in jiffies */ + __entry->age,/* dirtied_before in relative milliseconds */ __entry->moved,__print_symbolic (__entry->reason,WB_WORK_REASON ), (unsigned long)__entry->cgroup_ino
Greg Kroah-Hartman
maintainerPATCH 190/255 XEN uses irqdesc::irq_data_common::handler_data to store a per interrupt XEN data pointer which contains XEN specific information.
In reply to Greg Kroah-HartmanFrom: Thomas Gleixner <[email protected]>
commit c330fb1ddc0a922f044989492b7fcca77ee1db46 upstream.
handler data is meant for interrupt handlers and not for storing irq chip specific information as some devices require handler data to store internal per interrupt information, e.g. pinctrl/GPIO chained interrupt handlers.
This obviously creates a conflict of interests and crashes the machine because the XEN pointer is overwritten by the driver pointer.
As the XEN data is not handler specific it should be stored in irqdesc::irq_data::chip_data instead.
A simple sed s/irq_[sg]et_handler_data/irq_[sg]et_chip_data/ cures that.
--- drivers/xen/events/events_base.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-)
drivers/xen/events/events_base.c +8 -8
@@ -156,7 +156,7 @@ int get_evtchn_to_irq(evtchn_port_t evtc/* Get info for IRQ */ struct irq_info *info_for_irq (unsigned irq) { -return irq_get_handler_data (irq); +return irq_get_chip_data (irq); }/* Constructors for packed IRQ information. */
@@ -377,7 +377,7 @@ static void xen_irq_init(unsigned irq) info->type =IRQT_UNBOUND ; info->refcnt =-1 ; -irq_set_handler_data (irq, info); +irq_set_chip_data (irq, info);list_add_tail (&info->list, &xen_irq_list_head); }
@@ -426,14 +426,14 @@ static int __must_check xen_allocate_irqstatic void xen_free_irq (unsigned irq) { -struct irq_info *info =irq_get_handler_data (irq); +struct irq_info *info =irq_get_chip_data (irq);if (WARN_ON (!info))return ;list_del (&info->list); -irq_set_handler_data (irq,NULL ); +irq_set_chip_data (irq,NULL );WARN_ON (info->refcnt >0 );
@@ -603,7 +603,7 @@ EXPORT_SYMBOL_GPL(xen_irq_from_gsi);static void __unbind_from_irq (unsigned int irq) {evtchn_port_t evtchn =evtchn_from_irq (irq); -struct irq_info *info =irq_get_handler_data (irq); +struct irq_info *info =irq_get_chip_data (irq);if (info->refcnt >0 ) { info->refcnt--;
@@ -1108,7 +1108,7 @@ int bind_ipi_to_irqhandler(enum ipi_vectvoid unbind_from_irqhandler (unsigned int irq,void *dev_id) { -struct irq_info *info =irq_get_handler_data (irq); +struct irq_info *info =irq_get_chip_data (irq);if (WARN_ON (!info))return ;
@@ -1142,7 +1142,7 @@ int evtchn_make_refcounted(evtchn_port_tif (irq ==-1 )return -ENOENT ; - info =irq_get_handler_data (irq); + info =irq_get_chip_data (irq);if (!info)return -ENOENT ;
@@ -1170,7 +1170,7 @@ int evtchn_get(evtchn_port_t evtchn)if (irq ==-1 ) goto done; - info =irq_get_handler_data (irq); + info =irq_get_chip_data (irq);if (!info) goto done;
Greg Kroah-Hartman
maintainerPATCH 191/255 usb: renesas-xhci: remove version check
In reply to Greg Kroah-HartmanFrom: Vinod Koul <[email protected]>
commit d66a57be2f9a315fc10d0f524f670fec903e0fb4 upstream.
Some devices in wild are reporting bunch of firmware versions, so remove the check for versions in driver
Reported by: Anastasios Vacharakis <[email protected]> Reported by: Glen Journeay <[email protected]>
Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=208911
--- drivers/usb/host/xhci-pci-renesas.c | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-)
drivers/usb/host/xhci-pci-renesas.c +1 -18
@@ -50,20 +50,6 @@#define RENESAS_RETRY 10000#define RENESAS_DELAY 10 -#define ROM_VALID_01 0x2013 -#define ROM_VALID_02 0x2026 - -static int renesas_verify_fw_version (struct pci_dev *pdev,u32 version) -{ -switch (version) { -case ROM_VALID_01 : -case ROM_VALID_02 : -return 0 ; - } -dev_err (&pdev->dev,"FW has invalid version :%d\n" , version); -return -EINVAL ; -} -static int renesas_fw_download_image (struct pci_dev *dev,const u32 *fw,size_t step,bool rom) {
@@ -202,10 +188,7 @@ static int renesas_check_rom_state(struc version &=RENESAS_FW_VERSION_FIELD ; version = version >>RENESAS_FW_VERSION_OFFSET ; - - err =renesas_verify_fw_version (pdev, version); -if (err) -return err; +dev_dbg (&pdev->dev,"Found ROM version: %x\n" , version);/* * Test if ROM is present and loaded, if so we can skip everything
Greg Kroah-Hartman
maintainerPATCH 192/255 usb: host: xhci-tegra: otg usb2/usb3 port init
In reply to Greg Kroah-HartmanFrom: JC Kuo <[email protected]>
commit 316a2868bc269be8c6e69ccc3a1f902a3f518eb9 upstream.
tegra_xusb_init_usb_phy() should initialize "otg_usb2_port" and "otg_usb3_port" with -EINVAL because "0" is a valid value represents usb2 port 0 or usb3 port 0.
--- drivers/usb/host/xhci-tegra.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/usb/host/xhci-tegra.c +2 -0
@@ -1258,6 +1258,8 @@ static int tegra_xusb_init_usb_phy(strucINIT_WORK (&tegra->id_work, tegra_xhci_id_work); tegra->id_nb.notifier_call = tegra_xhci_id_notify; + tegra->otg_usb2_port = -EINVAL ; + tegra->otg_usb3_port = -EINVAL ;for (i =0 ; i < tegra->num_usb_phys; i++) {struct phy *phy =tegra_xusb_get_phy (tegra,"usb2" , i);
Greg Kroah-Hartman
maintainerPATCH 193/255 usb: host: xhci-tegra: fix tegra_xusb_get_phy()
In reply to Greg Kroah-HartmanFrom: JC Kuo <[email protected]>
commit d54343a87732726b04ac5af873916b5ed4f52932 upstream.
tegra_xusb_get_phy() should take input argument "name".
--- drivers/usb/host/xhci-tegra.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/usb/host/xhci-tegra.c +1 -1
@@ -1136,7 +1136,7 @@ static struct phy *tegra_xusb_get_phy(stunsigned int i, phy_count =0 ;for (i =0 ; i < tegra->soc->num_types; i++) { -if (!strncmp (tegra->soc->phy_types[i].name,"usb2" , +if (!strncmp (tegra->soc->phy_types[i].name, name,strlen (name)))return tegra->phys[phy_count+port];
Greg Kroah-Hartman
maintainerPATCH 194/255 usb: host: xhci: fix ep context print mismatch in debugfs
In reply to Greg Kroah-HartmanFrom: Li Jun <[email protected]>
commit 0077b1b2c8d9ad5f7a08b62fb8524cdb9938388f upstream.
dci is 0 based and xhci_get_ep_ctx() will do ep index increment to get the ep context.
--- drivers/usb/host/xhci-debugfs.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/usb/host/xhci-debugfs.c +4 -4
@@ -273,7 +273,7 @@ static int xhci_slot_context_show(structstatic int xhci_endpoint_context_show (struct seq_file *s,void *unused) { -int dci; +int ep_index;dma_addr_t dma;struct xhci_hcd *xhci;struct xhci_ep_ctx *ep_ctx;
@@ -282,9 +282,9 @@ static int xhci_endpoint_context_show(st xhci =hcd_to_xhci (bus_to_hcd (dev->udev->bus)); -for (dci =1 ; dci <32 ; dci++) { - ep_ctx =xhci_get_ep_ctx (xhci, dev->out_ctx, dci); - dma = dev->out_ctx->dma + dci *CTX_SIZE (xhci->hcc_params); +for (ep_index =0 ; ep_index <31 ; ep_index++) { + ep_ctx =xhci_get_ep_ctx (xhci, dev->out_ctx, ep_index); + dma = dev->out_ctx->dma + (ep_index +1 ) *CTX_SIZE (xhci->hcc_params); seq_printf(s, "%pad: %s\n", &dma, xhci_decode_ep_context(le32_to_cpu(ep_ctx->ep_info), le32_to_cpu(ep_ctx->ep_info2),
Greg Kroah-Hartman
maintainerPATCH 195/255 xhci: Do warm-reset when both CAS and XDEV_RESUME are set
In reply to Greg Kroah-HartmanFrom: Kai-Heng Feng <[email protected]>
commit 904df64a5f4d5ebd670801d869ca0a6d6a6e8df6 upstream.
Sometimes re-plugging a USB device during system sleep renders the device useless:
[ 173.418345] xhci_hcd 0000:00:14.0: Get port status 2-4 read: 0x14203e2, return 0x10262 ... [ 176.496485] usb 2-4: Waited 2000ms for CONNECT [ 176.496781] usb usb2-port4: status 0000.0262 after resume, -19 [ 176.497103] usb 2-4: can't resume, status -19 [ 176.497438] usb usb2-port4: logical disconnect
Because PLS equals to XDEV_RESUME, xHCI driver reports U3 to usbcore, despite of CAS bit is flagged.
So proritize CAS over XDEV_RESUME to let usbcore handle warm-reset for the port.
--- drivers/usb/host/xhci-hub.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-)
drivers/usb/host/xhci-hub.c +10 -9
@@ -740,15 +740,6 @@ static void xhci_hub_report_usb3_link_st {u32 pls = status_reg &PORT_PLS_MASK ; -/* resume state is a xHCI internal state. -* Do not report it to usb core, instead, pretend to be U3, -* thus usb core knows it's not ready for transfer -*/ -if (pls ==XDEV_RESUME ) { - *status |=USB_SS_PORT_LS_U3 ; -return ; - } -/* When the CAS bit is set then warm reset * should be performed on port */
@@ -771,6 +762,16 @@ static void xhci_hub_report_usb3_link_st pls |=USB_PORT_STAT_CONNECTION ; }else {/* +* Resume state is an xHCI internal state. Do not report it to +* usb core, instead, pretend to be U3, thus usb core knows +* it's not ready for transfer. +*/ +if (pls ==XDEV_RESUME ) { + *status |=USB_SS_PORT_LS_U3 ; +return ; + } + +/* * If CAS bit isn't set but the Port is already at * Compliance Mode, fake a connection so the USB core * notices the Compliance state and resets the port.
Greg Kroah-Hartman
maintainerPATCH 196/255 xhci: Always restore EP_SOFT_CLEAR_TOGGLE even if ep reset failed
In reply to Greg Kroah-HartmanFrom: Ding Hui <[email protected]>
commit f1ec7ae6c9f8c016db320e204cb519a1da1581b8 upstream.
Some device drivers call libusb_clear_halt when target ep queue is not empty. (eg. spice client connected to qemu for usb redir)
Before commit f5249461b504 ("xhci: Clear the host side toggle manually when endpoint is soft reset"), that works well. But now, we got the error log:
EP not empty, refuse reset
xhci_endpoint_reset failed and left ep_state's EP_SOFT_CLEAR_TOGGLE bit still set
So all the subsequent urb sumbits to the ep will fail with the warn log:
Can't enqueue URB while manually clearing toggle
We need to clear ep_state EP_SOFT_CLEAR_TOGGLE bit after xhci_endpoint_reset, even if it failed.
--- drivers/usb/host/xhci.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/usb/host/xhci.c +2 -1
@@ -3236,10 +3236,11 @@ static void xhci_endpoint_reset(struct uwait_for_completion (cfg_cmd->completion); - ep->ep_state &= ~EP_SOFT_CLEAR_TOGGLE ;xhci_free_command (xhci, cfg_cmd); cleanup:xhci_free_command (xhci, stop_cmd); +if (ep->ep_state &EP_SOFT_CLEAR_TOGGLE ) + ep->ep_state &= ~EP_SOFT_CLEAR_TOGGLE ; } static int xhci_check_streams_endpoint(struct xhci_hcd *xhci,
Greg Kroah-Hartman
maintainerPATCH 197/255 io-wq: fix hang after cancelling pending hashed work
In reply to Greg Kroah-HartmanFrom: Pavel Begunkov <[email protected]>
commit 204361a77f4018627addd4a06877448f088ddfc0 upstream.
Don't forget to update wqe->hash_tail after cancelling a pending work item, if it was hashed.
--- fs/io-wq.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-)
fs/io-wq.c +19 -2
@@ -929,6 +929,24 @@ static bool io_wq_worker_cancel(struct ireturn match->nr_running && !match->cancel_all; } +static inline void io_wqe_remove_pending (struct io_wqe *wqe, +struct io_wq_work *work, +struct io_wq_work_node *prev) +{ +unsigned int hash =io_get_work_hash (work); +struct io_wq_work *prev_work =NULL ; + +if (io_wq_is_hashed (work) && work == wqe->hash_tail[hash]) { +if (prev) + prev_work = container_of(prev, struct io_wq_work, list); +if (prev_work &&io_get_work_hash (prev_work) == hash) + wqe->hash_tail[hash] = prev_work; +else + wqe->hash_tail[hash] =NULL ; + } +wq_list_del (&wqe->work_list, &work->list, prev); +} +static void io_wqe_cancel_pending_work (struct io_wqe *wqe,struct io_cb_cancel_data *match) {
@@ -942,8 +960,7 @@ retry: work = container_of(node, struct io_wq_work, list);if (!match->fn (work, match->data))continue ; - -wq_list_del (&wqe->work_list, node, prev); +io_wqe_remove_pending (wqe, work, prev);spin_unlock_irqrestore (&wqe->lock, flags);io_run_cancel (work, wqe); match->nr_pending++;
Greg Kroah-Hartman
maintainerPATCH 198/255 KVM: arm64: Set HCR_EL2.PTW to prevent AT taking synchronous exception
In reply to Greg Kroah-HartmanFrom: James Morse <[email protected]>
commit 71a7f8cb1ca4ca7214a700b1243626759b6c11d4 upstream.
AT instructions do a translation table walk and return the result, or the fault in PAR_EL1. KVM uses these to find the IPA when the value is not provided by the CPU in HPFAR_EL1.
If a translation table walk causes an external abort it is taken as an exception, even if it was due to an AT instruction. (DDI0487F.a's D5.2.11 "Synchronous faults generated by address translation instructions")
While we previously made KVM resilient to exceptions taken due to AT instructions, the device access causes mismatched attributes, and may occur speculatively. Prevent this, by forbidding a walk through memory described as device at stage2. Now such AT instructions will report a stage2 fault.
Such a fault will cause KVM to restart the guest. If the AT instructions always walk the page tables, but guest execution uses the translation cached in the TLB, the guest can't make forward progress until the TLB entry is evicted. This isn't a problem, as since commit 5dcd0fdbb492 ("KVM: arm64:
Defer guest entry when an asynchronous exception is pending"), KVM will return to the host to process IRQs allowing the rest of the system to keep running.
--- arch/arm64/include/asm/kvm_arm.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
arch/arm64/include/asm/kvm_arm.h +2 -1
@@ -71,11 +71,12 @@* IMO: Override CPSR.I and enable signaling with VI * FMO: Override CPSR.F and enable signaling with VF * SWIO: Turn set/way invalidates into set/way clean+invalidate +* PTW: Take a stage2 fault if a stage1 walk steps in device memory */ #define HCR_GUEST_FLAGS (HCR_TSC | HCR_TSW | HCR_TWE | HCR_TWI | HCR_VM | \ HCR_BSU_IS | HCR_FB | HCR_TAC | \ HCR_AMO | HCR_SWIO | HCR_TIDCP | HCR_RW | HCR_TLOR | \ - HCR_FMO | HCR_IMO) + HCR_FMO | HCR_IMO | HCR_PTW )#define HCR_VIRT_EXCP_MASK (HCR_VSE | HCR_VI | HCR_VF)#define HCR_HOST_NVHE_FLAGS (HCR_RW | HCR_API | HCR_APK)#define HCR_HOST_VHE_FLAGS (HCR_RW | HCR_TGE | HCR_E2H)
Greg Kroah-Hartman
maintainerPATCH 199/255 arm64: vdso32: make vdso32 install conditional
In reply to Greg Kroah-HartmanFrom: Frank van der Linden <[email protected]>
commit 5d28ba5f8a0cfa3a874fa96c33731b8fcd141b3a upstream.
vdso32 should only be installed if CONFIG_COMPAT_VDSO is enabled, since it's not even supposed to be compiled otherwise, and arm64 builds without a 32bit crosscompiler will fail.
--- arch/arm64/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
arch/arm64/Makefile +2 -1
@@ -158,7 +158,8 @@ zinstall install: PHONY += vdso_install vdso_install: $(Q)$(MAKE) $(build)=arch/arm64/kernel/vdso $@ - $(Q)$(MAKE) $(build)=arch/arm64/kernel/vdso32 $@ + $(if $(CONFIG_COMPAT_VDSO), \ + $(Q)$(MAKE) $(build)=arch/arm64/kernel/vdso32 $@) # We use MRPROPER_FILES and CLEAN_FILES now archclean:
Greg Kroah-Hartman
maintainerPATCH 200/255 PM: sleep: core: Fix the handling of pending runtime resume requests
In reply to Greg Kroah-HartmanFrom: Rafael J. Wysocki <[email protected]>
commit e3eb6e8fba65094328b8dca635d00de74ba75b45 upstream.
It has been reported that system-wide suspend may be aborted in the absence of any wakeup events due to unforseen interactions of it with the runtume PM framework.
One failing scenario is when there are multiple devices sharing an ACPI power resource and runtime-resume needs to be carried out for one of them during system-wide suspend (for example, because it needs to be reconfigured before the whole system goes to sleep). In that case, the runtime-resume of that device involves turning the ACPI power resource "on" which in turn causes runtime-resume requests to be queued up for all of the other devices sharing it. Those requests go to the runtime PM workqueue which is frozen during system-wide suspend, so they are not actually taken care of until the resume of the whole system, but the pm_runtime_barrier() call in __device_suspend() sees them and triggers system wakeup events for them which then cause the system-wide suspend to be aborted if wakeup source objects are in active use.
Of course, the logic that leads to triggering those wakeup events is questionable in the first place, because clearly there are cases in which a pending runtime resume request for a device is not connected to any real wakeup events in any way (like the one above). Moreover, it is racy, because the device may be resuming already by the time the pm_runtime_barrier() runs and so if the driver doesn't take care of signaling the wakeup event as appropriate, it will be lost. However, if the driver does take care of that, the extra pm_wakeup_event() call in the core is redundant.
Accordingly, drop the conditional pm_wakeup_event() call fron __device_suspend() and make the latter call pm_runtime_barrier() alone. Also modify the comment next to that call to reflect the new code and extend it to mention the need to avoid unwanted interactions between runtime PM and system-wide device suspend callbacks.
--- drivers/base/power/main.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-)
drivers/base/power/main.c +10 -6
@@ -1606,13 +1606,17 @@ static int __device_suspend(struct devic }/* -* If a device configured to wake up the system from sleep states -* has been suspended at run time and there's a resume request pending -* for it, this is equivalent to the device signaling wakeup, so the -* system suspend operation should be aborted. +* Wait for possible runtime PM transitions of the device in progress +* to complete and if there's a runtime resume request pending for it, +* resume it before proceeding with invoking the system-wide suspend +* callbacks for it. +* +* If the system-wide suspend callbacks below change the configuration +* of the device, they must disable runtime PM for it or otherwise +* ensure that its runtime-resume callbacks will not be confused by that +* change in case they are invoked going forward. */ -if (pm_runtime_barrier (dev) &&device_may_wakeup (dev)) -pm_wakeup_event (dev,0 ); +pm_runtime_barrier (dev);if (pm_wakeup_pending ()) { dev->power.direct_complete = false;
Greg Kroah-Hartman
maintainerPATCH 201/255 powerpc/32s: Disable VMAP stack which CONFIG_ADB_PMU
In reply to Greg Kroah-HartmanFrom: Christophe Leroy <[email protected]>
commit 4a133eb351ccc275683ad49305d0b04dde903733 upstream.
low_sleep_handler() can't restore the context from virtual stack because the stack can hardly be accessed with MMU OFF.
For now, disable VMAP stack when CONFIG_ADB_PMU is selected.
--- arch/powerpc/platforms/Kconfig.cputype | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/powerpc/platforms/Kconfig.cputype +1 -1
@@ -36,7 +36,7 @@ config PPC_BOOK3S_6xx select PPC_HAVE_PMU_SUPPORT select PPC_HAVE_KUEP select PPC_HAVE_KUAP - select HAVE_ARCH_VMAP_STACK + select HAVE_ARCH_VMAP_STACK if !ADB_PMU config PPC_BOOK3S_601 bool "PowerPC 601"
Greg Kroah-Hartman
maintainerPATCH 202/255 powerpc/perf: Fix crashes with generic_compat_pmu & BHRB
In reply to Greg Kroah-HartmanFrom: Alexey Kardashevskiy <[email protected]>
commit b460b512417ae9c8b51a3bdcc09020cd6c60ff69 upstream.
The bhrb_filter_map ("The Branch History Rolling Buffer") callback is only defined in raw CPUs' power_pmu structs. The "architected" CPUs use generic_compat_pmu, which does not have this callback, and crashes occur if a user tries to enable branch stack for an event.
This add a NULL pointer check for bhrb_filter_map() which behaves as if the callback returned an error.
This does not add the same check for config_bhrb() as the only caller checks for cpuhw->bhrb_users which remains zero if bhrb_filter_map==0.
--- arch/powerpc/perf/core-book3s.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-)
arch/powerpc/perf/core-book3s.c +14 -5
@@ -1517,9 +1517,16 @@ nocheck: ret =0 ; out:if (has_branch_stack (event)) { -power_pmu_bhrb_enable (event); - cpuhw->bhrb_filter = ppmu->bhrb_filter_map ( - event->attr.branch_sample_type); +u64 bhrb_filter =-1 ; + +if (ppmu->bhrb_filter_map) + bhrb_filter = ppmu->bhrb_filter_map ( + event->attr.branch_sample_type); + +if (bhrb_filter !=-1 ) { + cpuhw->bhrb_filter = bhrb_filter; +power_pmu_bhrb_enable (event); + } }perf_pmu_enable (event->pmu);
@@ -1841,7 +1848,6 @@ static int power_pmu_event_init(struct pint n;int err;struct cpu_hw_events *cpuhw; -u64 bhrb_filter;if (!ppmu)return -ENOENT ;
@@ -1947,7 +1953,10 @@ static int power_pmu_event_init(struct p err =power_check_constraints (cpuhw, events, cflags, n +1 );if (has_branch_stack (event)) { - bhrb_filter = ppmu->bhrb_filter_map ( +u64 bhrb_filter =-1 ; + +if (ppmu->bhrb_filter_map) + bhrb_filter = ppmu->bhrb_filter_map ( event->attr.branch_sample_type);if (bhrb_filter ==-1 ) {
Greg Kroah-Hartman
maintainerPATCH 203/255 device property: Fix the secondary firmware node handling in set_primary_fwnode()
In reply to Greg Kroah-HartmanFrom: Heikki Krogerus <[email protected]>
commit c15e1bdda4365a5f17cdadf22bf1c1df13884a9e upstream.
When the primary firmware node pointer is removed from a device (set to NULL) the secondary firmware node pointer, when it exists, is made the primary node for the device. However, the secondary firmware node pointer of the original primary firmware node is never cleared (set to NULL).
To avoid situation where the secondary firmware node pointer is pointing to a non-existing object, clearing it properly when the primary node is removed from a device in set_primary_fwnode().
--- drivers/base/core.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-)
drivers/base/core.c +8 -4
@@ -3988,9 +3988,9 @@ static inline bool fwnode_is_primary(str*/ void set_primary_fwnode (struct device *dev,struct fwnode_handle *fwnode) { -if (fwnode) { -struct fwnode_handle *fn = dev->fwnode; +struct fwnode_handle *fn = dev->fwnode; +if (fwnode) {if (fwnode_is_primary (fn)) fn = fn->secondary;
@@ -4000,8 +4000,12 @@ void set_primary_fwnode(struct device *d } dev->fwnode = fwnode; }else { - dev->fwnode =fwnode_is_primary (dev->fwnode) ? - dev->fwnode->secondary :NULL ; +if (fwnode_is_primary (fn)) { + dev->fwnode = fn->secondary; + fn->secondary =NULL ; + }else { + dev->fwnode =NULL ; + } } }EXPORT_SYMBOL_GPL (set_primary_fwnode);
Greg Kroah-Hartman
maintainerPATCH 204/255 crypto: af_alg - Work around empty control messages without MSG_MORE
In reply to Greg Kroah-HartmanFrom: Herbert Xu <[email protected]>
commit c195d66a8a75c60515819b101975f38b7ec6577f upstream.
The iwd daemon uses libell which sets up the skcipher operation with two separate control messages. As the first control message is sent without MSG_MORE, it is interpreted as an empty request.
While libell should be fixed to use MSG_MORE where appropriate, this patch works around the bug in the kernel so that existing binaries continue to work.
We will print a warning however.
A separate issue is that the new kernel code no longer allows the control message to be sent twice within the same request. This restriction is obviously incompatible with what iwd was doing (first setting an IV and then sending the real control message). This patch changes the kernel so that this is explicitly allowed.
--- crypto/af_alg.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-)
crypto/af_alg.c +10 -3
@@ -16,6 +16,7 @@#include <linux/module.h> #include <linux/net.h> #include <linux/rwsem.h> +#include <linux/sched.h> #include <linux/sched/signal.h> #include <linux/security.h>
@@ -847,9 +848,15 @@ int af_alg_sendmsg(struct socket *sock, }lock_sock (sk); -if (ctx->init && (init || !ctx->more)) { - err = -EINVAL ; - goto unlock; +if (ctx->init && !ctx->more) { +if (ctx->used) { + err = -EINVAL ; + goto unlock; + } + +pr_info_once ( +"%s sent an empty control message without MSG_MORE.\n" , + current->comm); } ctx->init = true;
Greg Kroah-Hartman
maintainerPATCH 205/255 usbip: Implement a match function to fix usbip
In reply to Greg Kroah-HartmanFrom: M. Vefa Bicakci <[email protected]>
commit 7a2f2974f26542b4e7b9b4321edb3cbbf3eeb91a upstream.
Commit 88b7381a939d ("USB: Select better matching USB drivers when available") introduced the use of a "match" function to select a non-generic/better driver for a particular USB device. This unfortunately breaks the operation of usbip in general, as reported in the kernel bugzilla with bug 208267 (linked below).
Upon inspecting the aforementioned commit, one can observe that the original code in the usb_device_match function used to return 1 unconditionally, but the aforementioned commit makes the usb_device_match function use identifier tables and "match" virtual functions, if either of them are available.
Hence, this commit implements a match function for usbip that unconditionally returns true to ensure that usbip is functional again.
This change has been verified to restore usbip functionality, with a v5.7.y kernel on an up-to-date version of Qubes OS 4.0, which uses usbip to redirect USB devices between VMs.
Thanks to Jonathan Dieter for the effort in bisecting this issue down to the aforementioned commit.
--- drivers/usb/usbip/stub_dev.c | 6 ++++++ 1 file changed, 6 insertions(+)
drivers/usb/usbip/stub_dev.c +6 -0
@@ -461,6 +461,11 @@ static void stub_disconnect(struct usb_dreturn ; } +static bool usbip_match (struct usb_device *udev) +{ +return true; +} +#ifdef CONFIG_PM /* These functions need usb_port_suspend and usb_port_resume,
@@ -486,6 +491,7 @@ struct usb_device_driver stub_driver = { .name = "usbip-host", .probe = stub_probe, .disconnect = stub_disconnect, + .match = usbip_match, #ifdef CONFIG_PM .suspend = stub_suspend, .resume = stub_resume,
Greg Kroah-Hartman
maintainerPATCH 206/255 genirq/matrix: Deal with the sillyness of for_each_cpu() on UP
In reply to Greg Kroah-HartmanFrom: Thomas Gleixner <[email protected]>
commit 784a0830377d0761834e385975bc46861fea9fa0 upstream.
Most of the CPU mask operations behave the same way, but for_each_cpu() and it's variants ignore the cpumask argument and claim that CPU0 is always in the mask. This is historical, inconsistent and annoying behaviour.
The matrix allocator uses for_each_cpu() and can be called on UP with an empty cpumask. The calling code does not expect that this succeeds but until commit e027fffff799 ("x86/irq: Unbreak interrupt affinity setting") this went unnoticed. That commit added a WARN_ON() to catch cases which move an interrupt from one vector to another on the same CPU. The warning triggers on UP.
Add a check for the cpumask being empty to prevent this.
--- kernel/irq/matrix.c | 7 +++++++ 1 file changed, 7 insertions(+)
kernel/irq/matrix.c +7 -0
@@ -380,6 +380,13 @@ int irq_matrix_alloc(struct irq_matrix *unsigned int cpu, bit;struct cpumap *cm; +/* +* Not required in theory, but matrix_find_best_cpu() uses +* for_each_cpu() which ignores the cpumask on UP . +*/ +if (cpumask_empty (msk)) +return -EINVAL ; + cpu =matrix_find_best_cpu (m, msk);if (cpu ==UINT_MAX )return -ENOSPC ;
Greg Kroah-Hartman
maintainerPATCH 207/255 irqchip/stm32-exti: Avoid losing interrupts due to clearing pending bits by mistake
In reply to Greg Kroah-HartmanFrom: qiuguorui1 <[email protected]>
commit e579076ac0a3bebb440fab101aef3c42c9f4c709 upstream.
In the current code, when the eoi callback of the exti clears the pending bit of the current interrupt, it will first read the values of fpr and rpr, then logically OR the corresponding bit of the interrupt number, and finally write back to fpr and rpr.
We found through experiments that if two exti interrupts,
we call them int1/int2, arrive almost at the same time. in our scenario, the time difference is 30 microseconds, assuming int1 is triggered first.
there will be an extreme scenario: both int's pending bit are set to 1, the irq handle of int1 is executed first, and eoi handle is then executed, at this moment, all pending bits are cleared, but the int 2 has not finally been reported to the cpu yet, which eventually lost int2.
According to stm32's TRM description about rpr and fpr: Writing a 1 to this bit will trigger a rising edge event on event x, Writing 0 has no effect.
Therefore, when clearing the pending bit, we only need to clear the pending bit of the irq.
--- drivers/irqchip/irq-stm32-exti.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-)
drivers/irqchip/irq-stm32-exti.c +12 -2
@@ -431,6 +431,16 @@ static void stm32_irq_ack(struct irq_datirq_gc_unlock (gc); } +/* directly set the target bit without reading first. */ +static inline void stm32_exti_write_bit (struct irq_data *d,u32 reg) +{ +struct stm32_exti_chip_data *chip_data =irq_data_get_irq_chip_data (d); +void __iomem *base = chip_data->host_data->base; +u32 val =BIT (d->hwirq %IRQS_PER_BANK ); + +writel_relaxed (val, base + reg); +} +static inline u32 stm32_exti_set_bit (struct irq_data *d,u32 reg) {struct stm32_exti_chip_data *chip_data =irq_data_get_irq_chip_data (d);
@@ -464,9 +474,9 @@ static void stm32_exti_h_eoi(struct irq_raw_spin_lock (&chip_data->rlock); -stm32_exti_set_bit (d, stm32_bank->rpr_ofst); +stm32_exti_write_bit (d, stm32_bank->rpr_ofst);if (stm32_bank->fpr_ofst !=UNDEF_REG ) -stm32_exti_set_bit (d, stm32_bank->fpr_ofst); +stm32_exti_write_bit (d, stm32_bank->fpr_ofst);raw_spin_unlock (&chip_data->rlock);
Greg Kroah-Hartman
maintainerPATCH 208/255 x86/irq: Unbreak interrupt affinity setting
In reply to Greg Kroah-HartmanFrom: Thomas Gleixner <[email protected]>
commit e027fffff799cdd70400c5485b1a54f482255985 upstream.
Several people reported that 5.8 broke the interrupt affinity setting mechanism.
The consolidation of the entry code reused the regular exception entry code for device interrupts and changed the way how the vector number is conveyed from ptregs->orig_ax to a function argument.
The low level entry uses the hardware error code slot to push the vector number onto the stack which is retrieved from there into a function argument and the slot on stack is set to -1.
The reason for setting it to -1 is that the error code slot is at the position where pt_regs::orig_ax is. A positive value in pt_regs::orig_ax indicates that the entry came via a syscall. If it's not set to a negative value then a signal delivery on return to userspace would try to restart a syscall. But there are other places which rely on pt_regs::orig_ax being a valid indicator for syscall entry.
But setting pt_regs::orig_ax to -1 has a nasty side effect vs. the interrupt affinity setting mechanism, which was overlooked when this change was made.
Moving interrupts on x86 happens in several steps. A new vector on a different CPU is allocated and the relevant interrupt source is reprogrammed to that. But that's racy and there might be an interrupt already in flight to the old vector. So the old vector is preserved until the first interrupt arrives on the new vector and the new target CPU. Once that happens the old vector is cleaned up, but this cleanup still depends on the vector number being stored in pt_regs::orig_ax, which is now -1.
That -1 makes the check for cleanup: pt_regs::orig_ax == new_vector always false. As a consequence the interrupt is moved once, but then it cannot be moved anymore because the cleanup of the old vector never happens.
There would be several ways to convey the vector information to that place in the guts of the interrupt handling, but on deeper inspection it turned out that this check is pointless and a leftover from the old affinity model of X86 which supported multi-CPU affinities. Under this model it was possible that an interrupt had an old and a new vector on the same CPU, so the vector match was required.
Under the new model the effective affinity of an interrupt is always a single CPU from the requested affinity mask. If the affinity mask changes then either the interrupt stays on the CPU and on the same vector when that CPU is still in the new affinity mask or it is moved to a different CPU, but it is never moved to a different vector on the same CPU.
Ergo the cleanup check for the matching vector number is not required and can be removed which makes the dependency on pt_regs:orig_ax go away.
The remaining check for new_cpu == smp_processsor_id() is completely sufficient. If it matches then the interrupt was successfully migrated and the cleanup can proceed.
For paranoia sake add a warning into the vector assignment code to validate that the assumption of never moving to a different vector on the same CPU holds.
--- arch/x86/kernel/apic/vector.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-)
arch/x86/kernel/apic/vector.c +9 -7
@@ -161,6 +161,7 @@ static void apic_update_vector(struct ir apicd->move_in_progress = true; apicd->prev_vector = apicd->vector; apicd->prev_cpu = apicd->cpu; +WARN_ON_ONCE (apicd->cpu == newcpu); }else {irq_matrix_free (vector_matrix, apicd->cpu, apicd->vector, managed);
@@ -910,7 +911,7 @@ void send_cleanup_vector(struct irq_cfg__send_cleanup_vector (apicd); } -static void __irq_complete_move (struct irq_cfg *cfg,unsigned vector) +void irq_complete_move (struct irq_cfg *cfg) {struct apic_chip_data *apicd;
@@ -918,15 +919,16 @@ static void __irq_complete_move(struct iif (likely (!apicd->move_in_progress))return ; -if (vector == apicd->vector && apicd->cpu ==smp_processor_id ()) +/* +* If the interrupt arrived on the new target CPU, cleanup the +* vector on the old target CPU. A vector check is not required +* because an interrupt can never move from one vector to another +* on the same CPU. +*/ +if (apicd->cpu ==smp_processor_id ())__send_cleanup_vector (apicd); } -void irq_complete_move (struct irq_cfg *cfg) -{ -__irq_complete_move (cfg, ~get_irq_regs ()->orig_ax); -} -/* * Called from fixup_irqs() with @desc->lock held and interrupts disabled. */
Greg Kroah-Hartman
maintainerPATCH 209/255 x86/hotplug: Silence APIC only after all interrupts are migrated
In reply to Greg Kroah-HartmanFrom: Ashok Raj <[email protected]>
commit 52d6b926aabc47643cd910c85edb262b7f44c168 upstream.
There is a race when taking a CPU offline. Current code looks like this:
native_cpu_disable()
{
...
apic_soft_disable();
/*
* Any existing set bits for pending interrupt to
* this CPU are preserved and will be sent via IPI
* to another CPU by fixup_irqs().
*/
cpu_disable_common();
{
....
/*
* Race window happens here. Once local APIC has been
* disabled any new interrupts from the device to
* the old CPU are lost
*/
fixup_irqs(); // Too late to capture anything in IRR.
...
}
}The fix is to disable the APIC *after* cpu_disable_common().
Testing was done with a USB NIC that provided a source of frequent interrupts. A script migrated interrupts to a specific CPU and then took that CPU offline.
--- arch/x86/kernel/smpboot.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-)
arch/x86/kernel/smpboot.c +20 -6
@@ -1604,14 +1604,28 @@ int native_cpu_disable(void)if (ret)return ret; -/* -* Disable the local APIC. Otherwise IPI broadcasts will reach -* it. It still responds normally to INIT, NMI, SMI, and SIPI -* messages. -*/ -apic_soft_disable ();cpu_disable_common (); +/* +* Disable the local APIC. Otherwise IPI broadcasts will reach +* it. It still responds normally to INIT, NMI, SMI, and SIPI +* messages. +* +* Disabling the APIC must happen after cpu_disable_common() +* which invokes fixup_irqs(). +* +* Disabling the APIC preserves already set bits in IRR, but +* an interrupt arriving after disabling the local APIC does not +* set the corresponding IRR bit. +* +* fixup_irqs() scans IRR for set bits so it can raise a not +* yet handled interrupt on the new destination CPU via an IPI +* but obviously it can't do so for IRR bits which are not set. +* IOW, interrupts arriving after disabling the local APIC will +* be lost. +*/ +apic_soft_disable (); +return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 210/255 drm/i915: Fix cmd parser desc matching with masks
In reply to Greg Kroah-HartmanFrom: Mika Kuoppala <[email protected]>
commit e5f10d6385cda083037915c12b130887c8831d2b upstream.
Our variety of defined gpu commands have the actual command id field and possibly length and flags applied.
We did start to apply the mask during initialization of the cmd descriptors but forgot to also apply it on comparisons.
Fix comparisons in order to properly deny access with associated commands.
v2: fix lri with correct mask (Chris)
--- drivers/gpu/drm/i915/i915_cmd_parser.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-)
drivers/gpu/drm/i915/i915_cmd_parser.c +10 -4
@@ -1204,6 +1204,12 @@ static u32 *copy_batch(struct drm_i915_greturn dst; } +static inline bool cmd_desc_is (const struct drm_i915_cmd_descriptor *const desc, +const u32 cmd) +{ +return desc->cmd.value == (cmd & desc->cmd.mask); +} +static bool check_cmd (const struct intel_engine_cs *engine,const struct drm_i915_cmd_descriptor *desc,const u32 *cmd,u32 length)
@@ -1242,19 +1248,19 @@ static bool check_cmd(const struct intel* allowed mask/value pair given in the whitelist entry. */ if (reg->mask) { -if (desc->cmd.value ==MI_LOAD_REGISTER_MEM ) { +if (cmd_desc_is (desc,MI_LOAD_REGISTER_MEM )) {DRM_DEBUG ("CMD: Rejected LRM to masked register 0x%08X\n" , reg_addr);return false; } -if (desc->cmd.value ==MI_LOAD_REGISTER_REG ) { +if (cmd_desc_is (desc,MI_LOAD_REGISTER_REG )) {DRM_DEBUG ("CMD: Rejected LRR to masked register 0x%08X\n" , reg_addr);return false; } -if (desc->cmd.value ==MI_LOAD_REGISTER_IMM (1 ) && +if (cmd_desc_is (desc,MI_LOAD_REGISTER_IMM (1 )) && (offset +2 > length || (cmd[offset +1 ] & reg->mask) != reg->value)) { DRM_DEBUG("CMD: Rejected LRI to masked register 0x%08X\n",
@@ -1478,7 +1484,7 @@ int intel_engine_cmd_parser(struct intelbreak ; } -if (desc->cmd.value ==MI_BATCH_BUFFER_START ) { +if (cmd_desc_is (desc,MI_BATCH_BUFFER_START )) { ret =check_bbstart (cmd, offset, length, batch_length, batch_addr, shadow_addr, jump_whitelist);
Greg Kroah-Hartman
maintainerPATCH 211/255 drm/etnaviv: fix external abort seen on GC600 rev 0x19
In reply to Greg Kroah-HartmanFrom: Christian Gmeiner <[email protected]>
commit 2c5bf028ef34745e7b3fe768f9c9355ecc7df101 upstream.
It looks like that this GPU core triggers an abort when reading VIVS_HI_CHIP_PRODUCT_ID and/or VIVS_HI_CHIP_ECO_ID.
I looked at different versions of Vivante's kernel driver and did not found anything about this issue or what feature flag can be used. So go the simplest route and do not read these two registers on the affected GPU core.
--- drivers/gpu/drm/etnaviv/etnaviv_gpu.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-)
drivers/gpu/drm/etnaviv/etnaviv_gpu.c +9 -2
@@ -337,9 +337,16 @@ static void etnaviv_hw_identify(struct e gpu->identity.model =gpu_read (gpu,VIVS_HI_CHIP_MODEL ); gpu->identity.revision =gpu_read (gpu,VIVS_HI_CHIP_REV ); - gpu->identity.product_id =gpu_read (gpu,VIVS_HI_CHIP_PRODUCT_ID ); gpu->identity.customer_id =gpu_read (gpu,VIVS_HI_CHIP_CUSTOMER_ID ); - gpu->identity.eco_id =gpu_read (gpu,VIVS_HI_CHIP_ECO_ID ); + +/* +* Reading these two registers on GC600 rev 0x19 result in a +* unhandled fault: external abort on non-linefetch +*/ +if (!etnaviv_is_model_rev (gpu,GC600 ,0x19 )) { + gpu->identity.product_id =gpu_read (gpu,VIVS_HI_CHIP_PRODUCT_ID ); + gpu->identity.eco_id =gpu_read (gpu,VIVS_HI_CHIP_ECO_ID ); + }/* * !!!! HACK ALERT !!!!
Greg Kroah-Hartman
maintainerPATCH 212/255 drm/dp_mst: Dont return error code when crtc is null
In reply to Greg Kroah-HartmanFrom: Bhawanpreet Lakha <[email protected]>
commit 88fee1c9007a38c19f2c558dc0ab1ddb4c323dc5 upstream.
[Why]
In certain cases the crtc can be NULL and returning -EINVAL causes atomic check to fail when it shouln't. This leads to valid configurations failing because atomic check fails.
[How]
Don't early return if crtc is null
--- drivers/gpu/drm/drm_dp_mst_topology.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/gpu/drm/drm_dp_mst_topology.c +2 -2
@@ -4993,8 +4993,8 @@ int drm_dp_mst_add_affected_dsc_crtcs(st crtc = conn_state->crtc; -if (WARN_ON (!crtc)) -return -EINVAL ; +if (!crtc) +continue ;if (!drm_dp_mst_dsc_aux_for_port (pos->port))continue ;
Greg Kroah-Hartman
maintainerPATCH 213/255 drm/modeset-lock: Take the modeset BKL for legacy drivers
In reply to Greg Kroah-HartmanFrom: Daniel Vetter <[email protected]>
commit 77ef38574beb3e0b414db48e9c0f04633df68ba6 upstream.
This fell off in the conversion in
commit 9bcaa3fe58ab7559e71df798bcff6e0795158695
Author: Michal Orzel <[email protected]> Date: Tue Apr 28 19:10:04 2020 +0200
drm: Replace drm_modeset_lock/unlock_all with DRM_MODESET_LOCK_ALL_* helpers
but it's caught by the drm_warn_on_modeset_not_all_locked() that the legacy modeset code uses. Since this is the bkl and it's unclear what's all protected, play it safe and grab it again for legacy drivers.
Unfortunately this means we need to sprinkle a few more #includes around.
Also we need to add the drm_device as a parameter to the _END macro.
Finally remove the mute_lock() from setcrtc, since that's now done by the macro.
--- drivers/gpu/drm/drm_atomic_helper.c | 7 ++++--- drivers/gpu/drm/drm_color_mgmt.c | 2 +- drivers/gpu/drm/drm_crtc.c | 4 +--- drivers/gpu/drm/drm_mode_object.c | 4 ++-- drivers/gpu/drm/drm_plane.c | 2 +- include/drm/drm_modeset_lock.h | 9 +++++++-- 6 files changed, 16 insertions(+), 12 deletions(-)
drivers/gpu/drm/drm_atomic_helper.c +4 -3
@@ -34,6 +34,7 @@#include <drm/drm_bridge.h> #include <drm/drm_damage_helper.h> #include <drm/drm_device.h> +#include <drm/drm_drv.h> #include <drm/drm_plane_helper.h> #include <drm/drm_print.h> #include <drm/drm_self_refresh_helper.h>
@@ -3105,7 +3106,7 @@ void drm_atomic_helper_shutdown(struct dif (ret)DRM_ERROR ("Disabling all crtc's during unload failed with %i\n" , ret); -DRM_MODESET_LOCK_ALL_END (ctx, ret); +DRM_MODESET_LOCK_ALL_END (dev, ctx, ret); }EXPORT_SYMBOL (drm_atomic_helper_shutdown);
@@ -3245,7 +3246,7 @@ struct drm_atomic_state *drm_atomic_help } unlock: -DRM_MODESET_LOCK_ALL_END (ctx, err); +DRM_MODESET_LOCK_ALL_END (dev, ctx, err);if (err)return ERR_PTR (err);
@@ -3326,7 +3327,7 @@ int drm_atomic_helper_resume(struct drm_ err =drm_atomic_helper_commit_duplicated_state (state, &ctx); -DRM_MODESET_LOCK_ALL_END (ctx, err); +DRM_MODESET_LOCK_ALL_END (dev, ctx, err);drm_atomic_state_put (state);return err;
drivers/gpu/drm/drm_color_mgmt.c +1 -1
@@ -294,7 +294,7 @@ int drm_mode_gamma_set_ioctl(struct drm_ crtc->gamma_size, &ctx); out: -DRM_MODESET_LOCK_ALL_END (ctx, ret); +DRM_MODESET_LOCK_ALL_END (dev, ctx, ret);return ret; }
drivers/gpu/drm/drm_crtc.c +1 -3
@@ -561,7 +561,6 @@ int drm_mode_setcrtc(struct drm_device *if (crtc_req->mode_valid && !drm_lease_held (file_priv, plane->base.id))return -EACCES ; -mutex_lock (&crtc->dev->mode_config.mutex);DRM_MODESET_LOCK_ALL_BEGIN (dev, ctx,DRM_MODESET_ACQUIRE_INTERRUPTIBLE , ret);
@@ -728,8 +727,7 @@ out: fb =NULL ; mode =NULL ; -DRM_MODESET_LOCK_ALL_END (ctx, ret); -mutex_unlock (&crtc->dev->mode_config.mutex); +DRM_MODESET_LOCK_ALL_END (dev, ctx, ret);return ret; }
drivers/gpu/drm/drm_mode_object.c +2 -2
@@ -428,7 +428,7 @@ int drm_mode_obj_get_properties_ioctl(st out_unref:drm_mode_object_put (obj); out: -DRM_MODESET_LOCK_ALL_END (ctx, ret); +DRM_MODESET_LOCK_ALL_END (dev, ctx, ret);return ret; }
@@ -470,7 +470,7 @@ static int set_property_legacy(struct drbreak ; }drm_property_change_valid_put (prop, ref); -DRM_MODESET_LOCK_ALL_END (ctx, ret); +DRM_MODESET_LOCK_ALL_END (dev, ctx, ret);return ret; }
drivers/gpu/drm/drm_plane.c +1 -1
@@ -791,7 +791,7 @@ static int setplane_internal(struct drm_ crtc_x, crtc_y, crtc_w, crtc_h, src_x, src_y, src_w, src_h, &ctx); -DRM_MODESET_LOCK_ALL_END (ctx, ret); +DRM_MODESET_LOCK_ALL_END (plane->dev, ctx, ret);return ret; }
include/drm/drm_modeset_lock.h +7 -2
@@ -164,6 +164,8 @@ int drm_modeset_lock_all_ctx(struct drm_* is 0, so no error checking is necessary */ #define DRM_MODESET_LOCK_ALL_BEGIN (dev, ctx, flags, ret) \ + if (!drm_drv_uses_atomic_modeset(dev)) \ + mutex_lock(&dev->mode_config.mutex); \ drm_modeset_acquire_init(&ctx, flags); \ modeset_lock_retry: \ ret = drm_modeset_lock_all_ctx(dev, &ctx); \
@@ -172,6 +174,7 @@ modeset_lock_retry: \/** * DRM_MODESET_LOCK_ALL_END - Helper to release and cleanup modeset locks +* @dev: drm device * @ctx: local modeset acquire context, will be dereferenced * @ret: local ret/err/etc variable to track error status *
@@ -188,7 +191,7 @@ modeset_lock_retry: \* to that failure. In both of these cases the code between BEGIN/END will not * be run, so the failure will reflect the inability to grab the locks. */ -#define DRM_MODESET_LOCK_ALL_END (ctx, ret) \ +#define DRM_MODESET_LOCK_ALL_END (dev, ctx, ret) \ modeset_lock_fail: \ if (ret == -EDEADLK) { \ ret = drm_modeset_backoff(&ctx); \
@@ -196,6 +199,8 @@ modeset_lock_fail: \ goto modeset_lock_retry; \ } \drm_modeset_drop_locks (&ctx); \ -drm_modeset_acquire_fini (&ctx); +drm_modeset_acquire_fini (&ctx); \ +if (!drm_drv_uses_atomic_modeset (dev)) \ +mutex_unlock (&dev->mode_config.mutex);#endif /* DRM_MODESET_LOCK_H_ */
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
Greg Kroah-Hartman
maintainerPATCH 214/255 drm/amdgpu: Fix buffer overflow in INFO ioctl
In reply to Greg Kroah-HartmanFrom: Alex Deucher <[email protected]>
commit b5b97cab55eb71daba3283c8b1d2cce456d511a1 upstream.
The values for "se_num" and "sh_num" come from the user in the ioctl. They can be in the 0-255 range but if they're more than AMDGPU_GFX_MAX_SE (4) or AMDGPU_GFX_MAX_SH_PER_SE (2) then it results in an out of bounds read.
--- drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +4 -0
@@ -663,8 +663,12 @@ static int amdgpu_info_ioctl(struct drm_* in the bitfields */ if (se_num ==AMDGPU_INFO_MMR_SE_INDEX_MASK ) se_num =0xffffffff ; +else if (se_num >=AMDGPU_GFX_MAX_SE ) +return -EINVAL ;if (sh_num ==AMDGPU_INFO_MMR_SH_INDEX_MASK ) sh_num =0xffffffff ; +else if (sh_num >=AMDGPU_GFX_MAX_SH_PER_SE ) +return -EINVAL ;if (info->read_mmr_reg.count >128 )return -EINVAL ;
Greg Kroah-Hartman
maintainerPATCH 215/255 drm/amd/display: use correct scale for actual_brightness
In reply to Greg Kroah-HartmanFrom: Alexander Monakov <[email protected]>
commit 69d9f4278d0f9d24607645f10e5ac5c59c77a4ac upstream.
Documentation for sysfs backlight level interface requires that values in both 'brightness' and 'actual_brightness' files are interpreted to be in range from 0 to the value given in the 'max_brightness' file.
With amdgpu, max_brightness gives 255, and values written by the user into 'brightness' are internally rescaled to a wider range. However, reading from 'actual_brightness' gives the raw register value without inverse rescaling. This causes issues for various userspace tools such as PowerTop and systemd that expect the value to be in the correct range.
Introduce a helper to retrieve internal backlight range. Use it to reimplement 'convert_brightness' as 'convert_brightness_from_user' and introduce 'convert_brightness_to_user'.
--- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 81 ++++++++++------------ 1 file changed, 40 insertions(+), 41 deletions(-)
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +40 -41
@@ -2882,51 +2882,50 @@ static int set_backlight_via_aux(structreturn rc ?0 :1 ; } -static u32 convert_brightness (const struct amdgpu_dm_backlight_caps *caps, -const uint32_t user_brightness) +static int get_brightness_range (const struct amdgpu_dm_backlight_caps *caps, +unsigned *min,unsigned *max) { -u32 min, max, conversion_pace; -u32 brightness = user_brightness; -if (!caps) - goto out; +return 0 ; -if (!caps->aux_support) { - max = caps->max_input_signal; - min = caps->min_input_signal; -/* -* The brightness input is in the range 0-255 -* It needs to be rescaled to be between the -* requested min and max input signal -* It also needs to be scaled up by 0x101 to -* match the DC interface which has a range of -* 0 to 0xffff -*/ - conversion_pace =0x101 ; - brightness = - user_brightness - * conversion_pace - * (max - min) - /AMDGPU_MAX_BL_LEVEL - + min * conversion_pace; +if (caps->aux_support) { +// Firmware limits are in nits, DC API wants millinits. + *max =1000 * caps->aux_max_input_signal; + *min =1000 * caps->aux_min_input_signal; }else { -/* TODO -* We are doing a linear interpolation here, which is OK but -* does not provide the optimal result. We probably want -* something close to the Perceptual Quantizer (PQ) curve. -*/ - max = caps->aux_max_input_signal; - min = caps->aux_min_input_signal; - - brightness = (AMDGPU_MAX_BL_LEVEL - user_brightness) * min - + user_brightness * max; -// Multiple the value by 1000 since we use millinits - brightness *=1000 ; - brightness =DIV_ROUND_CLOSEST (brightness,AMDGPU_MAX_BL_LEVEL ); +// Firmware limits are 8-bit, PWM control is 16-bit. + *max =0x101 * caps->max_input_signal; + *min =0x101 * caps->min_input_signal; } +return 1 ; +} + +static u32 convert_brightness_from_user (const struct amdgpu_dm_backlight_caps *caps, +uint32_t brightness) +{ +unsigned min, max; + +if (!get_brightness_range (caps, &min, &max)) +return brightness; + +// Rescale 0..255 to min..max +return min +DIV_ROUND_CLOSEST ((max - min) * brightness, +AMDGPU_MAX_BL_LEVEL ); +} + +static u32 convert_brightness_to_user (const struct amdgpu_dm_backlight_caps *caps, +uint32_t brightness) +{ +unsigned min, max; + +if (!get_brightness_range (caps, &min, &max)) +return brightness; -out: -return brightness; +if (brightness < min) +return 0 ; +// Rescale min..max to 0..255 +return DIV_ROUND_CLOSEST (AMDGPU_MAX_BL_LEVEL * (brightness - min), + max - min); }static int amdgpu_dm_backlight_update_status (struct backlight_device *bd)
@@ -2942,7 +2941,7 @@ static int amdgpu_dm_backlight_update_st link = (struct dc_link *)dm->backlight_link; - brightness =convert_brightness (&caps, bd->props.brightness); + brightness =convert_brightness_from_user (&caps, bd->props.brightness);// Change brightness based on AUX property if (caps.aux_support)return set_backlight_via_aux (link, brightness);
@@ -2959,7 +2958,7 @@ static int amdgpu_dm_backlight_get_brighif (ret ==DC_ERROR_UNEXPECTED )return bd->props.brightness; -return ret; +return convert_brightness_to_user (&dm->backlight_caps, ret); }static const struct backlight_ops amdgpu_dm_backlight_ops = {
Greg Kroah-Hartman
maintainerPATCH 216/255 drm/amdgpu/gfx10: refine mgcg setting
In reply to Greg Kroah-HartmanFrom: Jiansong Chen <[email protected]>
commit de7a1b0b8753e1b0000084f0e339ffab295d27ef upstream.
1. enable ENABLE_CGTS_LEGACY to fix specviewperf11 random hang.
2. remove obsolete RLC_CGTT_SCLK_OVERRIDE workaround.
--- drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +2 -4
@@ -6854,10 +6854,8 @@ static void gfx_v10_0_update_medium_grai def = data =RREG32_SOC15 (GC ,0 , mmRLC_CGTT_MGCG_OVERRIDE); data &= ~(RLC_CGTT_MGCG_OVERRIDE__GRBM_CGTT_SCLK_OVERRIDE_MASK |RLC_CGTT_MGCG_OVERRIDE__GFXIP_MGCG_OVERRIDE_MASK | -RLC_CGTT_MGCG_OVERRIDE__GFXIP_MGLS_OVERRIDE_MASK ); - -/* only for Vega10 & Raven1 */ - data |=RLC_CGTT_MGCG_OVERRIDE__RLC_CGTT_SCLK_OVERRIDE_MASK ; +RLC_CGTT_MGCG_OVERRIDE__GFXIP_MGLS_OVERRIDE_MASK | +RLC_CGTT_MGCG_OVERRIDE__ENABLE_CGTS_LEGACY_MASK );if (def != data)WREG32_SOC15 (GC ,0 , mmRLC_CGTT_MGCG_OVERRIDE, data);
Greg Kroah-Hartman
maintainerPATCH 217/255 drm/amd/powerplay: Fix hardmins not being sent to SMU for RV
In reply to Greg Kroah-HartmanFrom: Nicholas Kazlauskas <[email protected]>
commit e2bf3723db563457c0abe4eaeedac25bbbbd1d76 upstream.
[Why]
DC uses these to raise the voltage as needed for higher dispclk/dppclk and to ensure that we have enough bandwidth to drive the displays.
There's a bug preventing these from actuially sending messages since it's checking the actual clock (which is 0) instead of the incoming clock (which shouldn't be 0) when deciding to send the hardmin.
[How]
Check the clocks != 0 instead of the actual clocks.
--- drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-)
drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c +3 -6
@@ -204,8 +204,7 @@ static int smu10_set_min_deep_sleep_dcef {struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); -if (smu10_data->need_min_deep_sleep_dcefclk && - smu10_data->deep_sleep_dcefclk != clock) { +if (clock && smu10_data->deep_sleep_dcefclk != clock) { smu10_data->deep_sleep_dcefclk = clock; smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetMinDeepSleepDcefclk,
@@ -219,8 +218,7 @@ static int smu10_set_hard_min_dcefclk_by {struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); -if (smu10_data->dcf_actual_hard_min_freq && - smu10_data->dcf_actual_hard_min_freq != clock) { +if (clock && smu10_data->dcf_actual_hard_min_freq != clock) { smu10_data->dcf_actual_hard_min_freq = clock; smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetHardMinDcefclkByFreq,
@@ -234,8 +232,7 @@ static int smu10_set_hard_min_fclk_by_fr {struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); -if (smu10_data->f_actual_hard_min_freq && - smu10_data->f_actual_hard_min_freq != clock) { +if (clock && smu10_data->f_actual_hard_min_freq != clock) { smu10_data->f_actual_hard_min_freq = clock; smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetHardMinFclkByFreq,
Greg Kroah-Hartman
maintainerPATCH 218/255 drm/amd/pm: correct Vega10 swctf limit setting
In reply to Greg Kroah-HartmanFrom: Evan Quan <[email protected]>
commit b05d71b51078fc428c6b72582126d9d75d3c1f4c upstream.
Correct the Vega10 thermal swctf limit.
--- drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c +5 -2
@@ -363,6 +363,9 @@ int vega10_thermal_get_temperature(strucstatic int vega10_thermal_set_temperature_range (struct pp_hwmgr *hwmgr,struct PP_TemperatureRange *range) { +struct phm_ppt_v2_information *pp_table_info = + (struct phm_ppt_v2_information *)(hwmgr->pptable); +struct phm_tdp_table *tdp_table = pp_table_info->tdp_table;struct amdgpu_device *adev = hwmgr->adev;int low =VEGA10_THERMAL_MINIMUM_ALERT_TEMP *PP_TEMPERATURE_UNITS_PER_CENTIGRADES ;
@@ -372,8 +375,8 @@ static int vega10_thermal_set_temperaturif (low < range->min) low = range->min; -if (high > range->max) - high = range->max; +if (high > tdp_table->usSoftwareShutdownTemp) + high = tdp_table->usSoftwareShutdownTemp;if (low > high)return -EINVAL ;
Greg Kroah-Hartman
maintainerPATCH 219/255 drm/amd/pm: correct Vega12 swctf limit setting
In reply to Greg Kroah-HartmanFrom: Evan Quan <[email protected]>
commit e0ffd340249699ad27a6c91abdfa3e89f7823941 upstream.
Correct the Vega12 thermal swctf limit.
--- drivers/gpu/drm/amd/powerplay/hwmgr/vega12_thermal.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/gpu/drm/amd/powerplay/hwmgr/vega12_thermal.c +4 -2
@@ -170,6 +170,8 @@ int vega12_thermal_get_temperature(strucstatic int vega12_thermal_set_temperature_range (struct pp_hwmgr *hwmgr,struct PP_TemperatureRange *range) { +struct phm_ppt_v3_information *pptable_information = + (struct phm_ppt_v3_information *)hwmgr->pptable;struct amdgpu_device *adev = hwmgr->adev;int low =VEGA12_THERMAL_MINIMUM_ALERT_TEMP *PP_TEMPERATURE_UNITS_PER_CENTIGRADES ;
@@ -179,8 +181,8 @@ static int vega12_thermal_set_temperaturif (low < range->min) low = range->min; -if (high > range->max) - high = range->max; +if (high > pptable_information->us_software_shutdown_temp) + high = pptable_information->us_software_shutdown_temp;if (low > high)return -EINVAL ;
Greg Kroah-Hartman
maintainerPATCH 220/255 drm/amd/pm: correct Vega20 swctf limit setting
In reply to Greg Kroah-HartmanFrom: Evan Quan <[email protected]>
commit 9b51c4b2ba31396f3894ccc7df8bdf067243e9f5 upstream.
Correct the Vega20 thermal swctf limit.
--- drivers/gpu/drm/amd/powerplay/hwmgr/vega20_thermal.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/gpu/drm/amd/powerplay/hwmgr/vega20_thermal.c +4 -2
@@ -240,6 +240,8 @@ int vega20_thermal_get_temperature(strucstatic int vega20_thermal_set_temperature_range (struct pp_hwmgr *hwmgr,struct PP_TemperatureRange *range) { +struct phm_ppt_v3_information *pptable_information = + (struct phm_ppt_v3_information *)hwmgr->pptable;struct amdgpu_device *adev = hwmgr->adev;int low =VEGA20_THERMAL_MINIMUM_ALERT_TEMP *PP_TEMPERATURE_UNITS_PER_CENTIGRADES ;
@@ -249,8 +251,8 @@ static int vega20_thermal_set_temperaturif (low < range->min) low = range->min; -if (high > range->max) - high = range->max; +if (high > pptable_information->us_software_shutdown_temp) + high = pptable_information->us_software_shutdown_temp;if (low > high)return -EINVAL ;
Greg Kroah-Hartman
maintainerPATCH 221/255 drm/amd/pm: correct the thermal alert temperature limit settings
In reply to Greg Kroah-HartmanFrom: Evan Quan <[email protected]>
commit 28e628645333b7e581c4a7b04d958e4804ea10fe upstream.
Do the maths in celsius degree. This can fix the issues caused by the changes below:
drm/amd/pm: correct Vega20 swctf limit setting drm/amd/pm: correct Vega12 swctf limit setting drm/amd/pm: correct Vega10 swctf limit setting
--- drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c | 15 +++++++-------- drivers/gpu/drm/amd/powerplay/hwmgr/vega12_thermal.c | 15 +++++++-------- drivers/gpu/drm/amd/powerplay/hwmgr/vega20_thermal.c | 15 +++++++-------- 3 files changed, 21 insertions(+), 24 deletions(-)
drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c +7 -8
@@ -367,14 +367,13 @@ static int vega10_thermal_set_temperatur (struct phm_ppt_v2_information *)(hwmgr->pptable);struct phm_tdp_table *tdp_table = pp_table_info->tdp_table;struct amdgpu_device *adev = hwmgr->adev; -int low =VEGA10_THERMAL_MINIMUM_ALERT_TEMP * -PP_TEMPERATURE_UNITS_PER_CENTIGRADES ; -int high =VEGA10_THERMAL_MAXIMUM_ALERT_TEMP * -PP_TEMPERATURE_UNITS_PER_CENTIGRADES ; +int low =VEGA10_THERMAL_MINIMUM_ALERT_TEMP ; +int high =VEGA10_THERMAL_MAXIMUM_ALERT_TEMP ;uint32_t val; -if (low < range->min) - low = range->min; +/* compare them in unit celsius degree */ +if (low < range->min /PP_TEMPERATURE_UNITS_PER_CENTIGRADES ) + low = range->min /PP_TEMPERATURE_UNITS_PER_CENTIGRADES ;if (high > tdp_table->usSoftwareShutdownTemp) high = tdp_table->usSoftwareShutdownTemp;
@@ -385,8 +384,8 @@ static int vega10_thermal_set_temperatur val =REG_SET_FIELD (val,THM_THERMAL_INT_CTRL ,MAX_IH_CREDIT ,5 ); val =REG_SET_FIELD (val,THM_THERMAL_INT_CTRL ,THERM_IH_HW_ENA ,1 ); - val =REG_SET_FIELD (val,THM_THERMAL_INT_CTRL ,DIG_THERM_INTH , (high /PP_TEMPERATURE_UNITS_PER_CENTIGRADES )); - val =REG_SET_FIELD (val,THM_THERMAL_INT_CTRL ,DIG_THERM_INTL , (low /PP_TEMPERATURE_UNITS_PER_CENTIGRADES )); + val =REG_SET_FIELD (val,THM_THERMAL_INT_CTRL ,DIG_THERM_INTH , high); + val =REG_SET_FIELD (val,THM_THERMAL_INT_CTRL ,DIG_THERM_INTL , low); val &= (~THM_THERMAL_INT_CTRL__THERM_TRIGGER_MASK_MASK ) & (~THM_THERMAL_INT_CTRL__THERM_INTH_MASK_MASK ) & (~THM_THERMAL_INT_CTRL__THERM_INTL_MASK_MASK );
drivers/gpu/drm/amd/powerplay/hwmgr/vega12_thermal.c +7 -8
@@ -173,14 +173,13 @@ static int vega12_thermal_set_temperaturstruct phm_ppt_v3_information *pptable_information = (struct phm_ppt_v3_information *)hwmgr->pptable;struct amdgpu_device *adev = hwmgr->adev; -int low =VEGA12_THERMAL_MINIMUM_ALERT_TEMP * -PP_TEMPERATURE_UNITS_PER_CENTIGRADES ; -int high =VEGA12_THERMAL_MAXIMUM_ALERT_TEMP * -PP_TEMPERATURE_UNITS_PER_CENTIGRADES ; +int low =VEGA12_THERMAL_MINIMUM_ALERT_TEMP ; +int high =VEGA12_THERMAL_MAXIMUM_ALERT_TEMP ;uint32_t val; -if (low < range->min) - low = range->min; +/* compare them in unit celsius degree */ +if (low < range->min /PP_TEMPERATURE_UNITS_PER_CENTIGRADES ) + low = range->min /PP_TEMPERATURE_UNITS_PER_CENTIGRADES ;if (high > pptable_information->us_software_shutdown_temp) high = pptable_information->us_software_shutdown_temp;
@@ -191,8 +190,8 @@ static int vega12_thermal_set_temperatur val =REG_SET_FIELD (val,THM_THERMAL_INT_CTRL ,MAX_IH_CREDIT ,5 ); val =REG_SET_FIELD (val,THM_THERMAL_INT_CTRL ,THERM_IH_HW_ENA ,1 ); - val =REG_SET_FIELD (val,THM_THERMAL_INT_CTRL ,DIG_THERM_INTH , (high /PP_TEMPERATURE_UNITS_PER_CENTIGRADES )); - val =REG_SET_FIELD (val,THM_THERMAL_INT_CTRL ,DIG_THERM_INTL , (low /PP_TEMPERATURE_UNITS_PER_CENTIGRADES )); + val =REG_SET_FIELD (val,THM_THERMAL_INT_CTRL ,DIG_THERM_INTH , high); + val =REG_SET_FIELD (val,THM_THERMAL_INT_CTRL ,DIG_THERM_INTL , low); val = val & (~THM_THERMAL_INT_CTRL__THERM_TRIGGER_MASK_MASK );WREG32_SOC15 (THM ,0 , mmTHM_THERMAL_INT_CTRL, val);
drivers/gpu/drm/amd/powerplay/hwmgr/vega20_thermal.c +7 -8
@@ -243,14 +243,13 @@ static int vega20_thermal_set_temperaturstruct phm_ppt_v3_information *pptable_information = (struct phm_ppt_v3_information *)hwmgr->pptable;struct amdgpu_device *adev = hwmgr->adev; -int low =VEGA20_THERMAL_MINIMUM_ALERT_TEMP * -PP_TEMPERATURE_UNITS_PER_CENTIGRADES ; -int high =VEGA20_THERMAL_MAXIMUM_ALERT_TEMP * -PP_TEMPERATURE_UNITS_PER_CENTIGRADES ; +int low =VEGA20_THERMAL_MINIMUM_ALERT_TEMP ; +int high =VEGA20_THERMAL_MAXIMUM_ALERT_TEMP ;uint32_t val; -if (low < range->min) - low = range->min; +/* compare them in unit celsius degree */ +if (low < range->min /PP_TEMPERATURE_UNITS_PER_CENTIGRADES ) + low = range->min /PP_TEMPERATURE_UNITS_PER_CENTIGRADES ;if (high > pptable_information->us_software_shutdown_temp) high = pptable_information->us_software_shutdown_temp;
@@ -261,8 +260,8 @@ static int vega20_thermal_set_temperatur val =CGS_REG_SET_FIELD (val,THM_THERMAL_INT_CTRL ,MAX_IH_CREDIT ,5 ); val =CGS_REG_SET_FIELD (val,THM_THERMAL_INT_CTRL ,THERM_IH_HW_ENA ,1 ); - val =CGS_REG_SET_FIELD (val,THM_THERMAL_INT_CTRL ,DIG_THERM_INTH , (high /PP_TEMPERATURE_UNITS_PER_CENTIGRADES )); - val =CGS_REG_SET_FIELD (val,THM_THERMAL_INT_CTRL ,DIG_THERM_INTL , (low /PP_TEMPERATURE_UNITS_PER_CENTIGRADES )); + val =CGS_REG_SET_FIELD (val,THM_THERMAL_INT_CTRL ,DIG_THERM_INTH , high); + val =CGS_REG_SET_FIELD (val,THM_THERMAL_INT_CTRL ,DIG_THERM_INTL , low); val = val & (~THM_THERMAL_INT_CTRL__THERM_TRIGGER_MASK_MASK );WREG32_SOC15 (THM ,0 , mmTHM_THERMAL_INT_CTRL, val);
Greg Kroah-Hartman
maintainerPATCH 222/255 USB: yurex: Fix bad gfp argument
In reply to Greg Kroah-HartmanFrom: Alan Stern <[email protected]>
commit f176ede3a3bde5b398a6777a7f9ff091baa2d3ff upstream.
The syzbot fuzzer identified a bug in the yurex driver: It passes GFP_KERNEL as a memory-allocation flag to usb_submit_urb() at a time when its state is TASK_INTERRUPTIBLE, not TASK_RUNNING:
do not call blocking ops when !TASK_RUNNING; state=1 set at [<00000000370c7c68>] prepare_to_wait+0xb1/0x2a0 kernel/sched/wait.c:247
WARNING: CPU: 1 PID: 340 at kernel/sched/core.c:7253 __might_sleep+0x135/0x190 kernel/sched/core.c:7253 Kernel panic - not syncing: panic_on_warn set ... CPU: 1 PID: 340 Comm: syz-executor677 Not tainted 5.8.0-syzkaller #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 Call Trace: __dump_stack lib/dump_stack.c:77 [inline] dump_stack+0xf6/0x16e lib/dump_stack.c:118 panic+0x2aa/0x6e1 kernel/panic.c:231 __warn.cold+0x20/0x50 kernel/panic.c:600 report_bug+0x1bd/0x210 lib/bug.c:198 handle_bug+0x41/0x80 arch/x86/kernel/traps.c:234 exc_invalid_op+0x14/0x40 arch/x86/kernel/traps.c:254 asm_exc_invalid_op+0x12/0x20 arch/x86/include/asm/idtentry.h:536 RIP: 0010:__might_sleep+0x135/0x190 kernel/sched/core.c:7253 Code: 65 48 8b 1c 25 40 ef 01 00 48 8d 7b 10 48 89 fe 48 c1 ee 03 80 3c 06 00 75
2b 48 8b 73 10 48 c7 c7 e0 9e 06 86 e8 ed 12 f6 ff <0f> 0b e9 46 ff ff ff e8 1f b2 4b 00 e9 29 ff ff ff e8 15 b2 4b 00
RSP: 0018:ffff8881cdb77a28 EFLAGS: 00010282
RAX: 0000000000000000 RBX: ffff8881c6458000 RCX: 0000000000000000
RDX: ffff8881c6458000 RSI: ffffffff8129ec93 RDI: ffffed1039b6ef37
RBP: ffffffff86fdade2 R08: 0000000000000001 R09: ffff8881db32f54f
R10: 0000000000000000 R11: 0000000030343354 R12: 00000000000001f2
R13: 0000000000000000 R14: 0000000000000068 R15: ffffffff83c1b1aa
slab_pre_alloc_hook.constprop.0+0xea/0x200 mm/slab.h:498 slab_alloc_node mm/slub.c:2816 [inline] slab_alloc mm/slub.c:2900 [inline] kmem_cache_alloc_trace+0x46/0x220 mm/slub.c:2917 kmalloc include/linux/slab.h:554 [inline] dummy_urb_enqueue+0x7a/0x880 drivers/usb/gadget/udc/dummy_hcd.c:1251 usb_hcd_submit_urb+0x2b2/0x22d0 drivers/usb/core/hcd.c:1547 usb_submit_urb+0xb4e/0x13e0 drivers/usb/core/urb.c:570 yurex_write+0x3ea/0x820 drivers/usb/misc/yurex.c:495
This patch changes the call to use GFP_ATOMIC instead of GFP_KERNEL.
--- drivers/usb/misc/yurex.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/usb/misc/yurex.c +1 -1
@@ -492,7 +492,7 @@ static ssize_t yurex_write(struct file *prepare_to_wait (&dev->waitq, &wait,TASK_INTERRUPTIBLE );dev_dbg (&dev->interface->dev,"%s - submit %c\n" , __func__, dev->cntl_buffer[0 ]); - retval =usb_submit_urb (dev->cntl_urb,GFP_KERNEL ); + retval =usb_submit_urb (dev->cntl_urb,GFP_ATOMIC );if (retval >=0 ) timeout =schedule_timeout (YUREX_WRITE_TIMEOUT );finish_wait (&dev->waitq, &wait);
Greg Kroah-Hartman
maintainerPATCH 223/255 usb: uas: Add quirk for PNY Pro Elite
In reply to Greg Kroah-HartmanFrom: Thinh Nguyen <[email protected]>
commit 9a469bc9f32dd33c7aac5744669d21a023a719cd upstream.
PNY Pro Elite USB 3.1 Gen 2 device (SSD) doesn't respond to ATA_12 pass-through command (i.e. it just hangs). If it doesn't support this command, it should respond properly to the host. Let's just add a quirk to be able to move forward with other operations.
--- drivers/usb/storage/unusual_uas.h | 7 +++++++ 1 file changed, 7 insertions(+)
drivers/usb/storage/unusual_uas.h +7 -0
@@ -80,6 +80,13 @@ UNUSUAL_DEV(0x152d, 0x0578, 0x0000, 0x99 USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_BROKEN_FUA), +/* Reported-by: Thinh Nguyen <[email protected]> */ +UNUSUAL_DEV (0x154b ,0xf00d ,0x0000 ,0x9999 , +"PNY" , +"Pro Elite SSD" , +USB_SC_DEVICE ,USB_PR_DEVICE ,NULL , +US_FL_NO_ATA_1X ), +/* Reported-by: Hans de Goede <[email protected]> */ UNUSUAL_DEV(0x2109, 0x0711, 0x0000, 0x9999, "VIA",
Greg Kroah-Hartman
maintainerPATCH 224/255 USB: quirks: Add no-lpm quirk for another Raydium touchscreen
In reply to Greg Kroah-HartmanFrom: Kai-Heng Feng <[email protected]>
commit 5967116e8358899ebaa22702d09b0af57fef23e1 upstream.
There's another Raydium touchscreen needs the no-lpm quirk:
[ 1.339149] usb 1-9: New USB device found, idVendor=2386, idProduct=350e, bcdDevice= 0.00 [ 1.339150] usb 1-9: New USB device strings: Mfr=1, Product=2, SerialNumber=0 [ 1.339151] usb 1-9: Product: Raydium Touch System [ 1.339152] usb 1-9: Manufacturer: Raydium Corporation ... [ 6.450497] usb 1-9: can't set config #1, error -110
--- drivers/usb/core/quirks.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/usb/core/quirks.c +2 -0
@@ -465,6 +465,8 @@ static const struct usb_device_id usb_qu { USB_DEVICE(0x2386, 0x3119), .driver_info = USB_QUIRK_NO_LPM }, + { USB_DEVICE(0x2386, 0x350e), .driver_info = USB_QUIRK_NO_LPM }, + /* DJI CineSSD */ { USB_DEVICE(0x2ca3, 0x0031), .driver_info = USB_QUIRK_NO_LPM },
Greg Kroah-Hartman
maintainerPATCH 225/255 USB: quirks: Ignore duplicate endpoint on Sound Devices MixPre-D
In reply to Greg Kroah-HartmanFrom: Alan Stern <[email protected]>
commit 068834a2773b6a12805105cfadbb3d4229fc6e0a upstream.
The Sound Devices MixPre-D audio card suffers from the same defect as the Sound Devices USBPre2: an endpoint shared between a normal audio interface and a vendor-specific interface, in violation of the USB spec. Since the USB core now treats duplicated endpoints as bugs and ignores them, the audio endpoint isn't available and the card can't be used for audio capture.
Along the same lines as commit bdd1b147b802 ("USB: quirks: blacklist duplicate ep on Sound Devices USBPre2"), this patch adds a quirks entry saying to ignore ep5in for interface 1, leaving it available for use with standard audio interface 2.
--- drivers/usb/core/quirks.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/usb/core/quirks.c +5 -0
@@ -370,6 +370,10 @@ static const struct usb_device_id usb_qu { USB_DEVICE(0x0926, 0x0202), .driver_info = USB_QUIRK_ENDPOINT_BLACKLIST }, + /* Sound Devices MixPre-D */ + { USB_DEVICE(0x0926, 0x0208), .driver_info = + USB_QUIRK_ENDPOINT_BLACKLIST }, + /* Keytouch QWERTY Panel keyboard */ { USB_DEVICE(0x0926, 0x3333), .driver_info = USB_QUIRK_CONFIG_INTF_STRINGS },
@@ -511,6 +515,7 @@ static const struct usb_device_id usb_am*/ static const struct usb_device_id usb_endpoint_blacklist[] = { {USB_DEVICE_INTERFACE_NUMBER (0x0926 ,0x0202 ,1 ), .driver_info =0x85 }, + {USB_DEVICE_INTERFACE_NUMBER (0x0926 ,0x0208 ,1 ), .driver_info =0x85 }, { } };
Greg Kroah-Hartman
maintainerPATCH 226/255 USB: Ignore UAS for JMicron JMS567 ATA/ATAPI Bridge
In reply to Greg Kroah-HartmanFrom: Cyril Roelandt <[email protected]>
commit 9aa37788e7ebb3f489fb4b71ce07adadd444264a upstream.
This device does not support UAS properly and a similar entry already exists in drivers/usb/storage/unusual_uas.h. Without this patch, storage_probe() defers the handling of this device to UAS, which cannot handle it either.
--- drivers/usb/storage/unusual_devs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/usb/storage/unusual_devs.h +1 -1
@@ -2328,7 +2328,7 @@ UNUSUAL_DEV( 0x357d, 0x7788, 0x0114, 0x "JMicron", "USB to ATA/ATAPI Bridge", USB_SC_DEVICE, USB_PR_DEVICE, NULL, - US_FL_BROKEN_FUA ), + US_FL_BROKEN_FUA | US_FL_IGNORE_UAS ),/* Reported by Andrey Rahmatullin <[email protected]> */ UNUSUAL_DEV( 0x4102, 0x1020, 0x0100, 0x0100,
Greg Kroah-Hartman
maintainerPATCH 227/255 usb: host: ohci-exynos: Fix error handling in exynos_ohci_probe()
In reply to Greg Kroah-HartmanFrom: Tang Bin <[email protected]>
commit 1d4169834628d18b2392a2da92b7fbf5e8e2ce89 upstream.
If the function platform_get_irq() failed, the negative value returned will not be detected here. So fix error handling in exynos_ohci_probe(). And when get irq failed, the function platform_get_irq() logs an error message, so remove redundant message here.
--- drivers/usb/host/ohci-exynos.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
drivers/usb/host/ohci-exynos.c +2 -3
@@ -171,9 +171,8 @@ static int exynos_ohci_probe(struct plat hcd->rsrc_len =resource_size (res); irq =platform_get_irq (pdev,0 ); -if (!irq) { -dev_err (&pdev->dev,"Failed to get IRQ\n" ); - err = -ENODEV ; +if (irq <0 ) { + err = irq; goto fail_io; }
Greg Kroah-Hartman
maintainerPATCH 228/255 USB: gadget: u_f: add overflow checks to VLA macros
In reply to Greg Kroah-HartmanFrom: Brooke Basile <[email protected]>
commit b1cd1b65afba95971fa457dfdb2c941c60d38c5b upstream.
size can potentially hold an overflowed value if its assigned expression is left unchecked, leading to a smaller than needed allocation when vla_group_size() is used by callers to allocate memory.
To fix this, add a test for saturation before declaring variables and an overflow check to (n) * sizeof(type).
If the expression results in overflow, vla_group_size() will return SIZE_MAX.
--- drivers/usb/gadget/u_f.h | 38 +++++++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 11 deletions(-)
drivers/usb/gadget/u_f.h +27 -11
@@ -14,6 +14,7 @@#define __U_F_H__#include <linux/usb/gadget.h> +#include <linux/overflow.h> /* Variable Length Array Macros **********************************************/ #define vla_group (groupname) size_t groupname##__next = 0
@@ -21,21 +22,36 @@#define vla_item (groupname, type, name, n) \ size_t groupname##_##name##__offset = ({ \ - size_t align_mask = __alignof__(type) - 1; \ - size_t offset = (groupname##__next + align_mask) & ~align_mask;\ - size_t size = (n) * sizeof(type); \ - groupname##__next = offset + size; \ + size_t offset = 0; \ + if (groupname##__next != SIZE_MAX) { \ + size_t align_mask = __alignof__(type) - 1; \ + size_t offset = (groupname##__next + align_mask) \ + & ~align_mask; \ + size_t size = array_size(n, sizeof(type)); \ + if (check_add_overflow(offset, size, \ + &groupname##__next)) { \ + groupname##__next = SIZE_MAX; \ + offset = 0; \ + } \ + } \ offset; \ })#define vla_item_with_sz (groupname, type, name, n) \ - size_t groupname##_##name##__sz = (n) * sizeof(type); \ - size_t groupname##_##name##__offset = ({ \ - size_t align_mask = __alignof__(type) - 1; \ - size_t offset = (groupname##__next + align_mask) & ~align_mask;\ - size_t size = groupname##_##name##__sz; \ - groupname##__next = offset + size; \ - offset; \ + size_t groupname##_##name##__sz = array_size(n, sizeof(type)); \ + size_t groupname##_##name##__offset = ({ \ + size_t offset = 0; \ + if (groupname##__next != SIZE_MAX) { \ + size_t align_mask = __alignof__(type) - 1; \ + size_t offset = (groupname##__next + align_mask) \ + & ~align_mask; \ + if (check_add_overflow(offset, groupname##_##name##__sz,\ + &groupname##__next)) { \ + groupname##__next = SIZE_MAX; \ + offset = 0; \ + } \ + } \ + offset; \ })#define vla_ptr (ptr, groupname, name) \
Greg Kroah-Hartman
maintainerPATCH 229/255 USB: gadget: f_ncm: add bounds checks to ncm_unwrap_ntb()
In reply to Greg Kroah-HartmanFrom: Brooke Basile <[email protected]>
commit 2b74b0a04d3e9f9f08ff026e5663dce88ff94e52 upstream.
Some values extracted by ncm_unwrap_ntb() could possibly lead to several different out of bounds reads of memory. Specifically the values passed to netdev_alloc_skb_ip_align() need to be checked so that memory is not overflowed.
Resolve this by applying bounds checking to a number of different indexes and lengths of the structure parsing logic.
--- drivers/usb/gadget/function/f_ncm.c | 81 ++++++++++++++++++++++++++++++------ 1 file changed, 69 insertions(+), 12 deletions(-)
drivers/usb/gadget/function/f_ncm.c +69 -12
@@ -1181,12 +1181,15 @@ static int ncm_unwrap_ntb(struct getherint ndp_index;unsigned dg_len, dg_len2;unsigned ndp_len; +unsigned block_len;struct sk_buff *skb2;int ret = -EINVAL ; -unsigned max_size =le32_to_cpu (ntb_parameters.dwNtbOutMaxSize); +unsigned ntb_max =le32_to_cpu (ntb_parameters.dwNtbOutMaxSize); +unsigned frame_max =le16_to_cpu (ecm_desc.wMaxSegmentSize);const struct ndp_parser_opts *opts = ncm->parser_opts;unsigned crc_len = ncm->is_crc ?sizeof (uint32_t ) :0 ;int dgram_counter; +bool ndp_after_header;/* dwSignature */ if (get_unaligned_le32 (tmp) != opts->nth_sign) {
@@ -1205,25 +1208,37 @@ static int ncm_unwrap_ntb(struct gether } tmp++;/* skip wSequence */ + block_len =get_ncm (&tmp, opts->block_length);/* (d)wBlockLength */ -if (get_ncm (&tmp, opts->block_length) > max_size) { +if (block_len > ntb_max) {INFO (port->func.config->cdev,"OUT size exceeded\n" ); goto err; } ndp_index =get_ncm (&tmp, opts->ndp_index); + ndp_after_header = false;/* Run through all the NDP's in the NTB */ do { - /* NCM 3.2 */ - if (((ndp_index % 4) != 0) && - (ndp_index < opts->nth_size)) { + /* + * NCM 3.2 + * dwNdpIndex + */ + if (((ndp_index % 4) != 0) || + (ndp_index < opts->nth_size) || + (ndp_index > (block_len - + opts->ndp_size))) { INFO(port->func.config->cdev, "Bad index: %#X\n", ndp_index); goto err; } + if (ndp_index == opts->nth_size) + ndp_after_header = true; - /* walk through NDP */ + /* + * walk through NDP + * dwSignature + */ tmp = (void *)(skb->data + ndp_index); if (get_unaligned_le32(tmp) != ncm->ndp_sign) { INFO(port->func.config->cdev, "Wrong NDP SIGN\n");
@@ -1234,14 +1249,15 @@ static int ncm_unwrap_ntb(struct gether ndp_len =get_unaligned_le16 (tmp++);/* * NCM 3.3.1 +* wLength * entry is 2 items * item size is 16/32 bits, opts->dgram_item_len * 2 bytes * minimal: struct usb_cdc_ncm_ndpX + normal entry + zero entry * Each entry is a dgram index and a dgram length. */ if ((ndp_len < opts->ndp_size - +2 *2 * (opts->dgram_item_len *2 )) - || (ndp_len % opts->ndplen_align !=0 )) { + +2 *2 * (opts->dgram_item_len *2 )) || + (ndp_len % opts->ndplen_align !=0 )) {INFO (port->func.config->cdev,"Bad NDP length: %#X\n" , ndp_len); goto err;
@@ -1258,8 +1274,21 @@ static int ncm_unwrap_ntb(struct gether do { index = index2; + /* wDatagramIndex[0] */ + if ((index < opts->nth_size) || + (index > block_len - opts->dpe_size)) { + INFO(port->func.config->cdev, + "Bad index: %#X\n", index); + goto err; + } + dg_len = dg_len2; - if (dg_len < 14 + crc_len) { /* ethernet hdr + crc */ + /* + * wDatagramLength[0] + * ethernet hdr + crc or larger than max frame size + */ + if ((dg_len < 14 + crc_len) || + (dg_len > frame_max)) { INFO(port->func.config->cdev, "Bad dgram length: %#X\n", dg_len); goto err;
@@ -1283,6 +1312,37 @@ static int ncm_unwrap_ntb(struct gether index2 =get_ncm (&tmp, opts->dgram_item_len); dg_len2 =get_ncm (&tmp, opts->dgram_item_len); +if (index2 ==0 || dg_len2 ==0 ) +break ; + +/* wDatagramIndex[1] */ +if (ndp_after_header) { +if (index2 < opts->nth_size + opts->ndp_size) { +INFO (port->func.config->cdev, +"Bad index: %#X\n" , index2); + goto err; + } + }else { +if (index2 < opts->nth_size + opts->dpe_size) { +INFO (port->func.config->cdev, +"Bad index: %#X\n" , index2); + goto err; + } + } +if (index2 > block_len - opts->dpe_size) { +INFO (port->func.config->cdev, +"Bad index: %#X\n" , index2); + goto err; + } + +/* wDatagramLength[1] */ +if ((dg_len2 <14 + crc_len) || + (dg_len2 > frame_max)) { +INFO (port->func.config->cdev, +"Bad dgram length: %#X\n" , dg_len); + goto err; + } +/* * Copy the data into a new skb. * This ensures the truesize is correct
@@ -1299,9 +1359,6 @@ static int ncm_unwrap_ntb(struct gether ndp_len -=2 * (opts->dgram_item_len *2 ); dgram_counter++; - -if (index2 ==0 || dg_len2 ==0 ) -break ; }while (ndp_len >2 * (opts->dgram_item_len *2 )); }while (ndp_index);
Greg Kroah-Hartman
maintainerPATCH 230/255 USB: gadget: u_f: Unbreak offset calculation in VLAs
In reply to Greg Kroah-HartmanFrom: Andy Shevchenko <[email protected]>
commit bfd08d06d978d0304eb6f7855b548aa2cd1c5486 upstream.
Inadvertently the commit b1cd1b65afba ("USB: gadget: u_f: add overflow checks to VLA macros") makes VLA macros to always return 0 due to different scope of two variables of the same name. Obviously we need to have only one.
--- drivers/usb/gadget/u_f.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/usb/gadget/u_f.h +4 -4
@@ -25,9 +25,9 @@size_t offset =0 ; \ if (groupname##__next != SIZE_MAX) { \size_t align_mask = __alignof__(type ) -1 ; \ - size_t offset = (groupname##__next + align_mask) \ - & ~align_mask; \size_t size =array_size (n,sizeof (type)); \ + offset = (groupname##__next + align_mask) & \ + ~align_mask; \if (check_add_overflow (offset, size, \ &groupname##__next)) { \ groupname##__next = SIZE_MAX; \
@@ -43,8 +43,8 @@size_t offset =0 ; \ if (groupname##__next != SIZE_MAX) { \size_t align_mask = __alignof__(type ) -1 ; \ - size_t offset = (groupname##__next + align_mask) \ - & ~align_mask; \ + offset = (groupname##__next + align_mask) & \ + ~align_mask; \ if (check_add_overflow(offset, groupname##_##name##__sz,\ &groupname##__next)) { \ groupname##__next = SIZE_MAX; \
Greg Kroah-Hartman
maintainerPATCH 231/255 usb: dwc3: gadget: Dont setup more than requested
In reply to Greg Kroah-HartmanFrom: Thinh Nguyen <[email protected]>
commit 5d187c0454ef4c5e046a81af36882d4d515922ec upstream.
The SG list may be set up with entry size more than the requested length. Check the usb_request->length and make sure that we don't setup the TRBs to send/receive more than requested. This case may occur when the SG entry is allocated up to a certain minimum size, but the request length is less than that. It can also occur when the request is reused for a different request length.
--- drivers/usb/dwc3/gadget.c | 51 +++++++++++++++++++++++++++++++--------------- 1 file changed, 35 insertions(+), 16 deletions(-)
drivers/usb/dwc3/gadget.c +35 -16
@@ -1054,27 +1054,25 @@ static void __dwc3_prepare_one_trb(struc* dwc3_prepare_one_trb - setup one TRB from one request * @dep: endpoint for which this request is prepared * @req: dwc3_request pointer +* @trb_length: buffer size of the TRB * @chain: should this TRB be chained to the next? * @node: only for isochronous endpoints. First TRB needs different type. */ static void dwc3_prepare_one_trb (struct dwc3_ep *dep, -struct dwc3_request *req,unsigned chain,unsigned node) +struct dwc3_request *req,unsigned int trb_length, +unsigned chain,unsigned node) {struct dwc3_trb *trb; -unsigned int length;dma_addr_t dma;unsigned stream_id = req->request.stream_id;unsigned short_not_ok = req->request.short_not_ok;unsigned no_interrupt = req->request.no_interrupt;unsigned is_last = req->request.is_last; -if (req->request.num_sgs >0 ) { - length =sg_dma_len (req->start_sg); +if (req->request.num_sgs >0 ) dma =sg_dma_address (req->start_sg); - }else { - length = req->request.length; +else dma = req->request.dma; - } trb = &dep->trb_pool[dep->trb_enqueue];
@@ -1086,7 +1084,7 @@ static void dwc3_prepare_one_trb(struct req->num_trbs++; -__dwc3_prepare_one_trb (dep, trb, dma, length, chain, node, +__dwc3_prepare_one_trb (dep, trb, dma, trb_length, chain, node, stream_id, short_not_ok, no_interrupt, is_last); }
@@ -1096,16 +1094,27 @@ static void dwc3_prepare_one_trb_sg(strustruct scatterlist *sg = req->start_sg;struct scatterlist *s;int i; - +unsigned int length = req->request.length;unsigned int remaining = req->request.num_mapped_sgs - req->num_queued_sgs; +/* +* If we resume preparing the request, then get the remaining length of +* the request and resume where we left off. +*/ +for_each_sg (req->request.sg, s, req->num_queued_sgs, i) + length -=sg_dma_len (s); +for_each_sg (sg, s, remaining, i) { -unsigned int length = req->request.length;unsigned int maxp =usb_endpoint_maxp (dep->endpoint.desc);unsigned int rem = length % maxp; +unsigned int trb_length;unsigned chain = true; + trb_length = min_t(unsigned int, length, sg_dma_len(s)); + + length -= trb_length; +/* * IOMMU driver is coalescing the list of sgs which shares a * page boundary into one and giving it to USB driver. With
@@ -1113,7 +1122,7 @@ static void dwc3_prepare_one_trb_sg(stru* sgs passed. So mark the chain bit to false if it isthe last * mapped sg. */ -if (i == remaining -1 ) +if ((i == remaining -1 ) || !length) chain = false;if (rem &&usb_endpoint_dir_out (dep->endpoint.desc) && !chain) {
@@ -1123,7 +1132,7 @@ static void dwc3_prepare_one_trb_sg(stru req->needs_extra_trb = true;/* prepare normal TRB */ -dwc3_prepare_one_trb (dep, req, true, i); +dwc3_prepare_one_trb (dep, req, trb_length, true, i);/* Now prepare one extra TRB to align transfer size */ trb = &dep->trb_pool[dep->trb_enqueue];
@@ -1135,7 +1144,7 @@ static void dwc3_prepare_one_trb_sg(stru req->request.no_interrupt, req->request.is_last); }else { -dwc3_prepare_one_trb (dep, req, chain, i); +dwc3_prepare_one_trb (dep, req, trb_length, chain, i); }/*
@@ -1150,6 +1159,16 @@ static void dwc3_prepare_one_trb_sg(stru req->num_queued_sgs++; +/* +* The number of pending SG entries may not correspond to the +* number of mapped SG entries. If all the data are queued, then +* don't include unused SG entries. +*/ +if (length ==0 ) { + req->num_pending_sgs -= req->request.num_mapped_sgs - req->num_queued_sgs; +break ; + } +if (!dwc3_calc_trbs_left (dep))break ; }
@@ -1169,7 +1188,7 @@ static void dwc3_prepare_one_trb_linear( req->needs_extra_trb = true;/* prepare normal TRB */ -dwc3_prepare_one_trb (dep, req, true,0 ); +dwc3_prepare_one_trb (dep, req, length, true,0 );/* Now prepare one extra TRB to align transfer size */ trb = &dep->trb_pool[dep->trb_enqueue];
@@ -1187,7 +1206,7 @@ static void dwc3_prepare_one_trb_linear( req->needs_extra_trb = true;/* prepare normal TRB */ -dwc3_prepare_one_trb (dep, req, true,0 ); +dwc3_prepare_one_trb (dep, req, length, true,0 );/* Now prepare one extra TRB to handle ZLP */ trb = &dep->trb_pool[dep->trb_enqueue];
@@ -1198,7 +1217,7 @@ static void dwc3_prepare_one_trb_linear( req->request.no_interrupt, req->request.is_last); }else { -dwc3_prepare_one_trb (dep, req, false,0 ); +dwc3_prepare_one_trb (dep, req, length, false,0 ); } }
Greg Kroah-Hartman
maintainerPATCH 232/255 usb: dwc3: gadget: Fix handling ZLP
In reply to Greg Kroah-HartmanFrom: Thinh Nguyen <[email protected]>
commit d2ee3ff79e6a3d4105e684021017d100524dc560 upstream.
The usb_request->zero doesn't apply for isoc. Also, if we prepare a 0-length (ZLP) TRB for the OUT direction, we need to prepare an extra TRB to pad up to the MPS alignment. Use the same bounce buffer for the ZLP TRB and the extra pad TRB.
--- drivers/usb/dwc3/gadget.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-)
drivers/usb/dwc3/gadget.c +23 -2
@@ -1199,6 +1199,7 @@ static void dwc3_prepare_one_trb_linear( req->request.no_interrupt, req->request.is_last); }else if (req->request.zero && req->request.length && + !usb_endpoint_xfer_isoc (dep->endpoint.desc) && (IS_ALIGNED (req->request.length, maxp))) {struct dwc3 *dwc = dep->dwc;struct dwc3_trb *trb;
@@ -1208,14 +1209,25 @@ static void dwc3_prepare_one_trb_linear(/* prepare normal TRB */ dwc3_prepare_one_trb (dep, req, length, true,0 ); -/* Now prepare one extra TRB to handle ZLP */ +/* Prepare one extra TRB to handle ZLP */ trb = &dep->trb_pool[dep->trb_enqueue]; req->num_trbs++;__dwc3_prepare_one_trb (dep, trb, dwc->bounce_addr,0 , - false,1 , req->request.stream_id, + !req->direction,1 , req->request.stream_id, req->request.short_not_ok, req->request.no_interrupt, req->request.is_last); + +/* Prepare one more TRB to handle MPS alignment for OUT */ +if (!req->direction) { + trb = &dep->trb_pool[dep->trb_enqueue]; + req->num_trbs++; +__dwc3_prepare_one_trb (dep, trb, dwc->bounce_addr, maxp, + false,1 , req->request.stream_id, + req->request.short_not_ok, + req->request.no_interrupt, + req->request.is_last); + } }else {dwc3_prepare_one_trb (dep, req, length, false,0 ); }
@@ -2668,8 +2680,17 @@ static int dwc3_gadget_ep_cleanup_comple status);if (req->needs_extra_trb) { +unsigned int maxp =usb_endpoint_maxp (dep->endpoint.desc); + ret =dwc3_gadget_ep_reclaim_trb_linear (dep, req, event, status); + +/* Reclaim MPS padding TRB for ZLP */ +if (!req->direction && req->request.zero && req->request.length && + !usb_endpoint_xfer_isoc (dep->endpoint.desc) && + (IS_ALIGNED (req->request.length, maxp))) + ret =dwc3_gadget_ep_reclaim_trb_linear (dep, req, event, status); + req->needs_extra_trb = false; }
Greg Kroah-Hartman
maintainerPATCH 233/255 usb: dwc3: gadget: Handle ZLP for sg requests
In reply to Greg Kroah-HartmanFrom: Thinh Nguyen <[email protected]>
commit bc9a2e226ea95e1699f7590845554de095308b75 upstream.
Currently dwc3 doesn't handle usb_request->zero for SG requests. This change checks and prepares extra TRBs for the ZLP for SG requests.
--- drivers/usb/dwc3/gadget.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+)
drivers/usb/dwc3/gadget.c +31 -0
@@ -1143,6 +1143,37 @@ static void dwc3_prepare_one_trb_sg(stru req->request.short_not_ok, req->request.no_interrupt, req->request.is_last); + }else if (req->request.zero && req->request.length && + !usb_endpoint_xfer_isoc (dep->endpoint.desc) && + !rem && !chain) { +struct dwc3 *dwc = dep->dwc; +struct dwc3_trb *trb; + + req->needs_extra_trb = true; + +/* Prepare normal TRB */ +dwc3_prepare_one_trb (dep, req, trb_length, true, i); + +/* Prepare one extra TRB to handle ZLP */ + trb = &dep->trb_pool[dep->trb_enqueue]; + req->num_trbs++; +__dwc3_prepare_one_trb (dep, trb, dwc->bounce_addr,0 , + !req->direction,1 , + req->request.stream_id, + req->request.short_not_ok, + req->request.no_interrupt, + req->request.is_last); + +/* Prepare one more TRB to handle MPS alignment */ +if (!req->direction) { + trb = &dep->trb_pool[dep->trb_enqueue]; + req->num_trbs++; +__dwc3_prepare_one_trb (dep, trb, dwc->bounce_addr, maxp, + false,1 , req->request.stream_id, + req->request.short_not_ok, + req->request.no_interrupt, + req->request.is_last); + } }else {dwc3_prepare_one_trb (dep, req, trb_length, chain, i); }
Greg Kroah-Hartman
maintainerPATCH 234/255 USB: cdc-acm: rework notification_buffer resizing
In reply to Greg Kroah-HartmanFrom: Tom Rix <[email protected]>
commit f4b9d8a582f738c24ebeabce5cc15f4b8159d74e upstream.
Clang static analysis reports this error
cdc-acm.c:409:3: warning: Use of memory after it is freed
acm_process_notification(acm, (unsigned char *)dr);
There are three problems, the first one is that dr is not reset
The variable dr is set with
if (acm->nb_index)
dr = (struct usb_cdc_notification *)acm->notification_buffer;
But if the notification_buffer is too small it is resized with
if (acm->nb_size) {
kfree(acm->notification_buffer);
acm->nb_size = 0;
}
alloc_size = roundup_pow_of_two(expected_size);
/*
* kmalloc ensures a valid notification_buffer after a
* use of kfree in case the previous allocation was too
* small. Final freeing is done on disconnect.
*/
acm->notification_buffer =
kmalloc(alloc_size, GFP_ATOMIC);dr should point to the new acm->notification_buffer.
The second problem is any data in the notification_buffer is lost when the pointer is freed. In the normal case, the current data is accumulated in the notification_buffer here.
memcpy(&acm->notification_buffer[acm->nb_index], urb->transfer_buffer, copy_size);
When a resize happens, anything before
notification_buffer[acm->nb_index] is garbage.
The third problem is the acm->nb_index is not reset on a resizing buffer error.
So switch resizing to using krealloc and reassign dr and reset nb_index.
--- drivers/usb/class/cdc-acm.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-)
drivers/usb/class/cdc-acm.c +10 -12
@@ -378,21 +378,19 @@ static void acm_ctrl_irq(struct urb *urbif (current_size < expected_size) {/* notification is transmitted fragmented, reassemble */ if (acm->nb_size < expected_size) { -if (acm->nb_size) { -kfree (acm->notification_buffer); - acm->nb_size =0 ; - } +u8 *new_buffer; alloc_size =roundup_pow_of_two (expected_size); -/* -* kmalloc ensures a valid notification_buffer after a -* use of kfree in case the previous allocation was too -* small. Final freeing is done on disconnect. -*/ - acm->notification_buffer = -kmalloc (alloc_size,GFP_ATOMIC ); -if (!acm->notification_buffer) +/* Final freeing is done on disconnect. */ + new_buffer =krealloc (acm->notification_buffer, + alloc_size,GFP_ATOMIC ); +if (!new_buffer) { + acm->nb_index =0 ; goto exit; + } + + acm->notification_buffer = new_buffer; acm->nb_size = alloc_size; + dr = (struct usb_cdc_notification *)acm->notification_buffer; } copy_size = min(current_size,
Greg Kroah-Hartman
maintainerPATCH 235/255 usb: storage: Add unusual_uas entry for Sony PSZ drives
In reply to Greg Kroah-HartmanFrom: Alan Stern <[email protected]>
commit 20934c0de13b49a072fb1e0ca79fe0fe0e40eae5 upstream.
The PSZ-HA* family of USB disk drives from Sony can't handle the REPORT OPCODES command when using the UAS protocol. This patch adds an appropriate quirks entry.
--- drivers/usb/storage/unusual_uas.h | 7 +++++++ 1 file changed, 7 insertions(+)
drivers/usb/storage/unusual_uas.h +7 -0
@@ -28,6 +28,13 @@* and don't forget to CC: the USB development list <[email protected]> */ +/* Reported-by: Till Dörges <[email protected]> */ +UNUSUAL_DEV (0x054c ,0x087d ,0x0000 ,0x9999 , +"Sony" , +"PSZ-HA*" , +USB_SC_DEVICE ,USB_PR_DEVICE ,NULL , +US_FL_NO_REPORT_OPCODES ), +/* Reported-by: Julian Groß <[email protected]> */ UNUSUAL_DEV(0x059f, 0x105f, 0x0000, 0x9999, "LaCie",
Greg Kroah-Hartman
maintainerPATCH 236/255 USB: Also match device drivers using the ->match vfunc
In reply to Greg Kroah-HartmanFrom: Bastien Nocera <[email protected]>
commit adb6e6ac20eedcf1dce19dc75b224e63c0828ea1 upstream.
We only ever used the ID table matching before, but we should also support open-coded match functions.
--- drivers/usb/core/generic.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/usb/core/generic.c +3 -2
@@ -207,8 +207,9 @@ static int __check_usb_generic(struct dereturn 0 ;if (!udrv->id_table)return 0 ; - -return usb_device_match_id (udev, udrv->id_table) !=NULL ; +if (usb_device_match_id (udev, udrv->id_table) !=NULL ) +return 1 ; +return (udrv->match && udrv->match (udev)); }static bool usb_generic_driver_match (struct usb_device *udev)
Greg Kroah-Hartman
maintainerPATCH 237/255 USB: Fix device driver race
In reply to Greg Kroah-HartmanFrom: Bastien Nocera <[email protected]>
commit d5643d2249b279077427b2c2b2ffae9b70c95b0b upstream.
When a new device with a specialised device driver is plugged in, the new driver will be modprobe()'d but the driver core will attach the "generic" driver to the device.
After that, nothing will trigger a reprobe when the modprobe()'d device driver has finished initialising, as the device has the "generic" driver attached to it.
Trigger a reprobe ourselves when new specialised drivers get registered.
--- drivers/usb/core/driver.c | 40 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-)
drivers/usb/core/driver.c +38 -2
@@ -905,6 +905,35 @@ static int usb_uevent(struct device *devreturn 0 ; } +static bool is_dev_usb_generic_driver (struct device *dev) +{ +struct usb_device_driver *udd = dev->driver ? +to_usb_device_driver (dev->driver) :NULL ; + +return udd == &usb_generic_driver; +} + +static int __usb_bus_reprobe_drivers (struct device *dev,void *data) +{ +struct usb_device_driver *new_udriver = data; +struct usb_device *udev; +int ret; + +if (!is_dev_usb_generic_driver (dev)) +return 0 ; + + udev =to_usb_device (dev); +if (usb_device_match_id (udev, new_udriver->id_table) ==NULL && + (!new_udriver->match || new_udriver->match (udev) !=0 )) +return 0 ; + + ret =device_reprobe (dev); +if (ret && ret != -EPROBE_DEFER ) +dev_err (dev,"Failed to reprobe device (error %d)\n" , ret); + +return 0 ; +} +/** * usb_register_device_driver - register a USB device (not interface) driver * @new_udriver: USB operations for the device driver
@@ -934,13 +963,20 @@ int usb_register_device_driver(struct us retval =driver_register (&new_udriver->drvwrap.driver); -if (!retval) +if (!retval) {pr_info ("%s: registered new device driver %s\n" , usbcore_name, new_udriver->name); -else +/* +* Check whether any device could be better served with +* this new driver +*/ +bus_for_each_dev (&usb_bus_type,NULL , new_udriver, + __usb_bus_reprobe_drivers); + }else {printk (KERN_ERR "%s: error %d registering device " " driver %s\n" , usbcore_name, retval, new_udriver->name); + }return retval; }
Greg Kroah-Hartman
maintainerPATCH 238/255 usb: typec: ucsi: Fix AB BA lock inversion
In reply to Greg Kroah-HartmanFrom: Hans de Goede <[email protected]>
commit 0ff0705a2ef2929e9326c95df48bdbebb0dafaad upstream.
Lockdep reports an AB BA lock inversion between ucsi_init() and ucsi_handle_connector_change():
AB order:
1. ucsi_init takes ucsi->ppm_lock (it runs with that locked for the duration of the function)
2. usci_init eventually end up calling ucsi_register_displayport, which takes ucsi_connector->lock
BA order:
1. ucsi_handle_connector_change work is started, takes ucsi_connector->lock
2. ucsi_handle_connector_change calls ucsi_send_command which takes ucsi->ppm_lock
The ppm_lock really only needs to be hold during 2 functions:ucsi_reset_ppm() and ucsi_run_command().
This commit fixes the AB BA lock inversion by making ucsi_init drop the ucsi->ppm_lock before it starts registering ports; and replacing any ucsi_run_command() calls after this point with ucsi_send_command() (which is a wrapper around run_command taking the lock while handling the command).
Some of the replacing of ucsi_run_command with ucsi_send_command in the helpers used during port registration also fixes a number of code paths after registration which call ucsi_run_command() without holding the ppm_lock:
1. ucsi_altmode_update_active() call in ucsi/displayport.c
2. ucsi_register_altmodes() call from ucsi_handle_connector_change() (through ucsi_partner_change())
--- drivers/usb/typec/ucsi/ucsi.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-)
drivers/usb/typec/ucsi/ucsi.c +9 -9
@@ -205,7 +205,7 @@ void ucsi_altmode_update_active(struct uint i; command =UCSI_GET_CURRENT_CAM |UCSI_CONNECTOR_NUMBER (con->num); - ret =ucsi_run_command (con->ucsi, command, &cur,sizeof (cur)); + ret =ucsi_send_command (con->ucsi, command, &cur,sizeof (cur));if (ret <0 ) {if (con->ucsi->version >0x0100 ) { dev_err(con->ucsi->dev,
@@ -354,7 +354,7 @@ ucsi_register_altmodes_nvidia(struct ucs command |=UCSI_GET_ALTMODE_RECIPIENT (recipient); command |=UCSI_GET_ALTMODE_CONNECTOR_NUMBER (con->num); command |=UCSI_GET_ALTMODE_OFFSET (i); - len =ucsi_run_command (con->ucsi, command, &alt,sizeof (alt)); + len =ucsi_send_command (con->ucsi, command, &alt,sizeof (alt));/* * We are collecting all altmodes first and then registering. * Some type-C device will return zero length data beyond last
@@ -431,7 +431,7 @@ static int ucsi_register_altmodes(struct command |=UCSI_GET_ALTMODE_RECIPIENT (recipient); command |=UCSI_GET_ALTMODE_CONNECTOR_NUMBER (con->num); command |=UCSI_GET_ALTMODE_OFFSET (i); - len =ucsi_run_command (con->ucsi, command, alt,sizeof (alt)); + len =ucsi_send_command (con->ucsi, command, alt,sizeof (alt));if (len <=0 )return len;
@@ -904,7 +904,7 @@ static int ucsi_register_port(struct ucs/* Get connector capability */ command =UCSI_GET_CONNECTOR_CAPABILITY ; command |=UCSI_CONNECTOR_NUMBER (con->num); - ret =ucsi_run_command (ucsi, command, &con->cap,sizeof (con->cap)); + ret =ucsi_send_command (ucsi, command, &con->cap,sizeof (con->cap));if (ret <0 )return ret;
@@ -953,8 +953,7 @@ static int ucsi_register_port(struct ucs/* Get the status */ command =UCSI_GET_CONNECTOR_STATUS |UCSI_CONNECTOR_NUMBER (con->num); - ret =ucsi_run_command (ucsi, command, &con->status, -sizeof (con->status)); + ret =ucsi_send_command (ucsi, command, &con->status,sizeof (con->status));if (ret <0 ) {dev_err (ucsi->dev,"con%d: failed to get status\n" , con->num);return 0 ;
@@ -1044,6 +1043,8 @@ int ucsi_init(struct ucsi *ucsi) goto err_reset; } +mutex_unlock (&ucsi->ppm_lock); +/* Register all connectors */ for (i =0 ; i < ucsi->cap.num_connectors; i++) { ret =ucsi_register_port (ucsi, i);
@@ -1054,12 +1055,10 @@ int ucsi_init(struct ucsi *ucsi)/* Enable all notifications */ ucsi->ntfy =UCSI_ENABLE_NTFY_ALL ; command =UCSI_SET_NOTIFICATION_ENABLE | ucsi->ntfy; - ret =ucsi_run_command (ucsi, command,NULL ,0 ); + ret =ucsi_send_command (ucsi, command,NULL ,0 );if (ret <0 ) goto err_unregister; -mutex_unlock (&ucsi->ppm_lock); -return 0 ; err_unregister:
@@ -1071,6 +1070,7 @@ err_unregister: con->port =NULL ; } +mutex_lock (&ucsi->ppm_lock); err_reset:ucsi_reset_ppm (ucsi); err:
Greg Kroah-Hartman
maintainerPATCH 239/255 usb: typec: ucsi: Fix 2 unlocked ucsi_run_command calls
In reply to Greg Kroah-HartmanFrom: Hans de Goede <[email protected]>
commit 7e90057f125c8c852940b848e06e7a72f050fc6f upstream.
Fix 2 unlocked ucsi_run_command calls:
1. ucsi_handle_connector_change() contains one ucsi_send_command() call, which takes the ppm_lock for it; and one ucsi_run_command() call which relies on the caller have taking the ppm_lock. ucsi_handle_connector_change() does not take the lock, so the second (ucsi_run_command) calls should also be ucsi_send_command().
2. ucsi_get_pdos() gets called from ucsi_handle_connector_change() which does not hold the ppm_lock, so it also must use ucsi_send_command().
This commit also adds a WARN_ON(!mutex_is_locked(&ucsi->ppm_lock)); to ucsi_run_command() to avoid similar problems getting re-introduced in the future.
--- drivers/usb/typec/ucsi/ucsi.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/usb/typec/ucsi/ucsi.c +4 -2
@@ -152,6 +152,8 @@ static int ucsi_run_command(struct ucsiu8 length;int ret; +WARN_ON (!mutex_is_locked (&ucsi->ppm_lock)); + ret =ucsi_exec_command (ucsi, command);if (ret <0 )return ret;
@@ -502,7 +504,7 @@ static void ucsi_get_pdos(struct ucsi_co command |=UCSI_GET_PDOS_PARTNER_PDO (is_partner); command |=UCSI_GET_PDOS_NUM_PDOS (UCSI_MAX_PDOS -1 ); command |=UCSI_GET_PDOS_SRC_PDOS ; - ret =ucsi_run_command (ucsi, command, con->src_pdos, + ret =ucsi_send_command (ucsi, command, con->src_pdos,sizeof (con->src_pdos));if (ret <0 ) {dev_err (ucsi->dev,"UCSI_GET_PDOS failed (%d)\n" , ret);
@@ -681,7 +683,7 @@ static void ucsi_handle_connector_change*/ command =UCSI_GET_CAM_SUPPORTED ; command |=UCSI_CONNECTOR_NUMBER (con->num); -ucsi_run_command (con->ucsi, command,NULL ,0 ); +ucsi_send_command (con->ucsi, command,NULL ,0 ); }if (con->status.change &UCSI_CONSTAT_PARTNER_CHANGE )
Greg Kroah-Hartman
maintainerPATCH 240/255 usb: typec: ucsi: Rework ppm_lock handling
In reply to Greg Kroah-HartmanFrom: Hans de Goede <[email protected]>
commit 25794e3079d2a98547b6bf5764ef0240aa89b798 upstream.
The ppm_lock really only needs to be hold during 2 functions:ucsi_reset_ppm() and ucsi_run_command().
Push the taking of the lock down into these 2 functions, renaming ucsi_run_command() to ucsi_send_command() which was an existing wrapper already taking the lock for its callers.
This simplifies things for the callers and removes the difference between ucsi_send_command() and ucsi_run_command() which has led to various locking bugs in the past.
--- drivers/usb/typec/ucsi/ucsi.c | 56 ++++++++++++++++-------------------------- 1 file changed, 22 insertions(+), 34 deletions(-)
drivers/usb/typec/ucsi/ucsi.c +22 -34
@@ -146,42 +146,33 @@ static int ucsi_exec_command(struct ucsireturn UCSI_CCI_LENGTH (cci); } -static int ucsi_run_command (struct ucsi *ucsi,u64 command, -void *data,size_t size) +int ucsi_send_command (struct ucsi *ucsi,u64 command, +void *data,size_t size) {u8 length;int ret; -WARN_ON (!mutex_is_locked (&ucsi->ppm_lock)); +mutex_lock (&ucsi->ppm_lock); ret =ucsi_exec_command (ucsi, command);if (ret <0 ) -return ret; + goto out; length = ret;if (data) { ret = ucsi->ops->read (ucsi,UCSI_MESSAGE_IN , data, size);if (ret) -return ret; + goto out; } ret =ucsi_acknowledge_command (ucsi);if (ret) -return ret; - -return length; -} + goto out; -int ucsi_send_command (struct ucsi *ucsi,u64 command, -void *retval,size_t size) -{ -int ret; - -mutex_lock (&ucsi->ppm_lock); - ret =ucsi_run_command (ucsi, command, retval, size); + ret = length; +out:mutex_unlock (&ucsi->ppm_lock); -return ret; }EXPORT_SYMBOL_GPL (ucsi_send_command);
@@ -738,20 +729,24 @@ static int ucsi_reset_ppm(struct ucsi *uu32 cci;int ret; +mutex_lock (&ucsi->ppm_lock); + ret = ucsi->ops->async_write (ucsi,UCSI_CONTROL , &command,sizeof (command));if (ret <0 ) -return ret; + goto out; tmo = jiffies +msecs_to_jiffies (UCSI_TIMEOUT_MS ); do { - if (time_is_before_jiffies(tmo)) - return -ETIMEDOUT; + if (time_is_before_jiffies(tmo)) { + ret = -ETIMEDOUT; + goto out; + } ret = ucsi->ops->read(ucsi, UCSI_CCI, &cci, sizeof(cci)); if (ret) - return ret; + goto out; /* If the PPM is still doing something else, reset it again. */ if (cci & ~UCSI_CCI_RESET_COMPLETE) {
@@ -759,13 +754,15 @@ static int ucsi_reset_ppm(struct ucsi *u &command, sizeof(command));if (ret <0 ) -return ret; + goto out; }msleep (20 ); }while (!(cci &UCSI_CCI_RESET_COMPLETE )); -return 0 ; +out: +mutex_unlock (&ucsi->ppm_lock); +return ret; }static int ucsi_role_cmd (struct ucsi_connector *con,u64 command)
@@ -777,9 +774,7 @@ static int ucsi_role_cmd(struct ucsi_conu64 c;/* PPM most likely stopped responding. Resetting everything. */ -mutex_lock (&con->ucsi->ppm_lock);ucsi_reset_ppm (con->ucsi); -mutex_unlock (&con->ucsi->ppm_lock); c =UCSI_SET_NOTIFICATION_ENABLE | con->ucsi->ntfy;ucsi_send_command (con->ucsi, c,NULL ,0 );
@@ -1010,8 +1005,6 @@ int ucsi_init(struct ucsi *ucsi)int ret;int i; -mutex_lock (&ucsi->ppm_lock); -/* Reset the PPM */ ret =ucsi_reset_ppm (ucsi);if (ret) {
@@ -1022,13 +1015,13 @@ int ucsi_init(struct ucsi *ucsi)/* Enable basic notifications */ ucsi->ntfy =UCSI_ENABLE_NTFY_CMD_COMPLETE |UCSI_ENABLE_NTFY_ERROR ; command =UCSI_SET_NOTIFICATION_ENABLE | ucsi->ntfy; - ret =ucsi_run_command (ucsi, command,NULL ,0 ); + ret =ucsi_send_command (ucsi, command,NULL ,0 );if (ret <0 ) goto err_reset;/* Get PPM capabilities */ command =UCSI_GET_CAPABILITY ; - ret =ucsi_run_command (ucsi, command, &ucsi->cap,sizeof (ucsi->cap)); + ret =ucsi_send_command (ucsi, command, &ucsi->cap,sizeof (ucsi->cap));if (ret <0 ) goto err_reset;
@@ -1045,8 +1038,6 @@ int ucsi_init(struct ucsi *ucsi) goto err_reset; } -mutex_unlock (&ucsi->ppm_lock); -/* Register all connectors */ for (i =0 ; i < ucsi->cap.num_connectors; i++) { ret =ucsi_register_port (ucsi, i);
@@ -1072,12 +1063,9 @@ err_unregister: con->port =NULL ; } -mutex_lock (&ucsi->ppm_lock); err_reset:ucsi_reset_ppm (ucsi); err: -mutex_unlock (&ucsi->ppm_lock); -return ret; }EXPORT_SYMBOL_GPL (ucsi_init);
Greg Kroah-Hartman
maintainerPATCH 241/255 usb: typec: ucsi: Hold con->lock for the entire duration of ucsi_register_port()
In reply to Greg Kroah-HartmanFrom: Hans de Goede <[email protected]>
commit bed97b30968ba354035a020989df0623e52b5536 upstream.
Commit 081da1325d35 ("usb: typec: ucsi: displayport: Fix a potential race during registration") made the ucsi code hold con->lock in ucsi_register_displayport(). But we really don't want any interactions with the connector to run before the port-registration process is fully complete.
This commit moves the taking of con->lock from ucsi_register_displayport() into ucsi_register_port() to achieve this.
--- drivers/usb/typec/ucsi/displayport.c | 9 +-------- drivers/usb/typec/ucsi/ucsi.c | 31 ++++++++++++++++++++++--------- 2 files changed, 23 insertions(+), 17 deletions(-)
drivers/usb/typec/ucsi/displayport.c +1 -8
@@ -288,8 +288,6 @@ struct typec_altmode *ucsi_register_dispstruct typec_altmode *alt;struct ucsi_dp *dp; -mutex_lock (&con->lock); -/* We can't rely on the firmware with the capabilities. */ desc->vdo |=DP_CAP_DP_SIGNALING |DP_CAP_RECEPTACLE ;
@@ -298,15 +296,12 @@ struct typec_altmode *ucsi_register_disp desc->vdo |= all_assignments <<16 ; alt =typec_port_register_altmode (con->port, desc); -if (IS_ERR (alt)) { -mutex_unlock (&con->lock); +if (IS_ERR (alt))return alt; - } dp =devm_kzalloc (&alt->dev,sizeof (*dp),GFP_KERNEL );if (!dp) {typec_unregister_altmode (alt); -mutex_unlock (&con->lock);return ERR_PTR (-ENOMEM ); }
@@ -319,7 +314,5 @@ struct typec_altmode *ucsi_register_disp alt->ops = &ucsi_displayport_ops;typec_altmode_set_drvdata (alt, dp); -mutex_unlock (&con->lock); -return alt; }
drivers/usb/typec/ucsi/ucsi.c +22 -9
@@ -898,12 +898,15 @@ static int ucsi_register_port(struct ucs con->num = index +1 ; con->ucsi = ucsi; +/* Delay other interactions with the con until registration is complete */ +mutex_lock (&con->lock); +/* Get connector capability */ command =UCSI_GET_CONNECTOR_CAPABILITY ; command |=UCSI_CONNECTOR_NUMBER (con->num); ret =ucsi_send_command (ucsi, command, &con->cap,sizeof (con->cap));if (ret <0 ) -return ret; + goto out;if (con->cap.op_mode &UCSI_CONCAP_OPMODE_DRP ) cap->data =TYPEC_PORT_DRD ;
@@ -935,26 +938,32 @@ static int ucsi_register_port(struct ucs ret =ucsi_register_port_psy (con);if (ret) -return ret; + goto out;/* Register the connector */ con->port =typec_register_port (ucsi->dev, cap); -if (IS_ERR (con->port)) -return PTR_ERR (con->port); +if (IS_ERR (con->port)) { + ret =PTR_ERR (con->port); + goto out; + }/* Alternate modes */ ret =ucsi_register_altmodes (con,UCSI_RECIPIENT_CON ); -if (ret) +if (ret) {dev_err (ucsi->dev,"con%d: failed to register alt modes\n" , con->num); + goto out; + }/* Get the status */ command =UCSI_GET_CONNECTOR_STATUS |UCSI_CONNECTOR_NUMBER (con->num); ret =ucsi_send_command (ucsi, command, &con->status,sizeof (con->status));if (ret <0 ) {dev_err (ucsi->dev,"con%d: failed to get status\n" , con->num); -return 0 ; + ret =0 ; + goto out; } + ret =0 ;/* ucsi_send_command() returns length on success */ switch (UCSI_CONSTAT_PARTNER_TYPE (con->status.flags)) {case UCSI_CONSTAT_PARTNER_TYPE_UFP :
@@ -979,17 +988,21 @@ static int ucsi_register_port(struct ucsif (con->partner) { ret =ucsi_register_altmodes (con,UCSI_RECIPIENT_SOP ); -if (ret) +if (ret) {dev_err (ucsi->dev,"con%d: failed to register alternate modes\n" , con->num); -else + ret =0 ; + }else {ucsi_altmode_update_active (con); + } }trace_ucsi_register_port (con->num, &con->status); -return 0 ; +out: +mutex_unlock (&con->lock); +return ret; }/**
Greg Kroah-Hartman
maintainerPATCH 242/255 usb: typec: tcpm: Fix Fix source hard reset response for TDA 2.3.1.1 and TDA 2.3.1.2 failures
In reply to Greg Kroah-HartmanFrom: Badhri Jagan Sridharan <[email protected]>
commit 23e26d0577535f5ffe4ff8ed6d06e009553c0bca upstream.
The patch addresses the compliance test failures while running TDA 2.3.1.1 and TDA 2.3.1.2 of the "PD Communications Engine USB PD Compliance MOI" test plan published in https://www.usb.org/usbc.
For a product to be Type-C compliant, it's expected that these tests are run on usb.org certified Type-C compliance tester as mentioned in
https://www.usb.org/usbc.
While the purpose of TDA 2.3.1.1 and TDA 2.3.1.2 is to verify that the static and dynamic electrical capabilities of a Source meet the requirements for each PDO offered, while doing so, the tests also monitor that the timing of the VBUS waveform versus the messages meets the requirements for Hard Reset defined in PROT-PROC-HR-TSTR as mentioned in step 11 of TDA.2.3.1.1 and step 15 of TDA.2.3.1.2.
TDB.2.2.13.1: PROT-PROC-HR-TSTR Procedure and Checks for Tester Originated Hard Reset
Purpose: To perform the appropriate protocol checks relating to any circumstance in which the Hard Reset signal is sent by the Tester.
UUT is behaving as source:
The Tester sends a Hard Reset signal.
1. Check VBUS stays within present valid voltage range for tPSHardReset min (25ms) after last bit of Hard Reset signal. [PROT_PROC_HR_TSTR_1]
2. Check that VBUS starts to fall below present valid voltage range by tPSHardReset max (35ms). [PROT_PROC_HR_TSTR_2]
3. Check that VBUS reaches vSafe0V within tSafe0v max (650 ms). [PROT_PROC_HR_TSTR_3]
4. Check that VBUS starts rising to vSafe5V after a delay of tSrcRecover (0.66s - 1s) from reaching vSafe0V. [PROT_PROC_HR_TSTR_4]
5. Check that VBUS reaches vSafe5V within tSrcTurnOn max (275ms) of rising above vSafe0v max (0.8V). [PROT_PROC_HR_TSTR_5] Power Delivery Compliance Plan 139 6. Check that Source Capabilities are finished sending within tFirstSourceCap max (250ms) of VBUS reaching vSafe5v min. [PROT_PROC_HR_TSTR_6].
This is in line with 7.1.5 Response to Hard Resets of the USB Power Delivery Specification Revision 3.0, Version 1.2,
"Hard Reset Signaling indicates a communication failure has occurred and the Source Shall stop driving VCONN, Shall remove Rp from the VCONN pin and Shall drive VBUS to vSafe0V as shown in Figure 7-9. The USB connection May reset during a Hard Reset since the VBUS voltage will be less than vSafe5V for an extended period of time. After establishing the vSafe0V voltage condition on VBUS, the Source Shall wait tSrcRecover before re-applying VCONN and restoring VBUS to vSafe5V. A Source Shall conform to the VCONN timing as specified in [USB Type-C 1.3]."
With the above guidelines from the spec in mind, TCPM does not turn off VCONN while entering SRC_HARD_RESET_VBUS_OFF. The patch makes TCPM turn off VCONN while entering SRC_HARD_RESET_VBUS_OFF and turn it back on while entering SRC_HARD_RESET_VBUS_ON along with vbus instead of having VCONN on through hardreset.
Also, the spec clearly states that "After establishing the vSafe0V voltage condition on VBUS", the Source Shall wait tSrcRecover before re-applying VCONN and restoring VBUS to vSafe5V.
TCPM does not conform to this requirement. If the TCPC driver calls tcpm_vbus_change with vbus off signal, TCPM right away enters SRC_HARD_RESET_VBUS_ON without waiting for tSrcRecover.
For TCPC's which are buggy/does not call tcpm_vbus_change, TCPM assumes that the vsafe0v is instantaneous as TCPM only waits tSrcRecover instead of waiting for tSafe0v + tSrcRecover. This patch also fixes this behavior by making sure that TCPM waits for tSrcRecover before transitioning into SRC_HARD_RESET_VBUS_ON when tcpm_vbus_change is called by TCPC.
When TCPC does not call tcpm_vbus_change, TCPM assumes the worst case i.e. tSafe0v + tSrcRecover before transitioning into SRC_HARD_RESET_VBUS_ON.
--- drivers/usb/typec/tcpm/tcpm.c | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-)
drivers/usb/typec/tcpm/tcpm.c +25 -3
@@ -3321,13 +3321,31 @@ static void run_state_machine(struct tcptcpm_set_state (port,SNK_HARD_RESET_SINK_OFF ,0 );break ;case SRC_HARD_RESET_VBUS_OFF : -tcpm_set_vconn (port, true); +/* +* 7.1.5 Response to Hard Resets +* Hard Reset Signaling indicates a communication failure has occurred and the +* Source Shall stop driving VCONN, Shall remove Rp from the VCONN pin and Shall +* drive VBUS to vSafe0V as shown in Figure 7-9. +*/ +tcpm_set_vconn (port, false);tcpm_set_vbus (port, false);tcpm_set_roles (port, port->self_powered,TYPEC_SOURCE ,tcpm_data_role_for_source (port)); -tcpm_set_state (port,SRC_HARD_RESET_VBUS_ON ,PD_T_SRC_RECOVER ); +/* +* If tcpc fails to notify vbus off, TCPM will wait for PD_T_SAFE_0V + +* PD_T_SRC_RECOVER before turning vbus back on. +* From Table 7-12 Sequence Description for a Source Initiated Hard Reset: +* 4. Policy Engine waits tPSHardReset after sending Hard Reset Signaling and then +* tells the Device Policy Manager to instruct the power supply to perform a +* Hard Reset. The transition to vSafe0V Shall occur within tSafe0V (t2). +* 5. After tSrcRecover the Source applies power to VBUS in an attempt to +* re-establish communication with the Sink and resume USB Default Operation. +* The transition to vSafe5V Shall occur within tSrcTurnOn(t4). +*/ +tcpm_set_state (port,SRC_HARD_RESET_VBUS_ON ,PD_T_SAFE_0V +PD_T_SRC_RECOVER );break ;case SRC_HARD_RESET_VBUS_ON : +tcpm_set_vconn (port, true);tcpm_set_vbus (port, true); port->tcpc->set_pd_rx (port->tcpc, true);tcpm_set_attached_state (port, true);
@@ -3887,7 +3905,11 @@ static void _tcpm_pd_vbus_off(struct tcptcpm_set_state (port,SNK_HARD_RESET_WAIT_VBUS ,0 );break ;case SRC_HARD_RESET_VBUS_OFF : -tcpm_set_state (port,SRC_HARD_RESET_VBUS_ON ,0 ); +/* +* After establishing the vSafe0V voltage condition on VBUS, the Source Shall wait +* tSrcRecover before re-applying VCONN and restoring VBUS to vSafe5V. +*/ +tcpm_set_state (port,SRC_HARD_RESET_VBUS_ON ,PD_T_SRC_RECOVER );break ;case HARD_RESET_SEND :break ;
Greg Kroah-Hartman
maintainerPATCH 243/255 io_uring: dont recurse on tsk->sighand->siglock with signalfd
In reply to Greg Kroah-HartmanFrom: Jens Axboe <[email protected]>
[ Upstream commit fd7d6de2241453fc7d042336d366a939a25bc5a9 ]
If an application is doing reads on signalfd, and we arm the poll handler because there's no data available, then the wakeup can recurse on the tasks sighand->siglock as the signal delivery from task_work_add() will use TWA_SIGNAL and that attempts to lock it again.
We can detect the signalfd case pretty easily by comparing the poll->head wait_queue_head_t with the target task signalfd wait queue. Just use normal task wakeup for this case.
--- fs/io_uring.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-)
fs/io_uring.c +13 -3
@@ -4114,7 +4114,8 @@ struct io_poll_table {int error; }; -static int io_req_task_work_add (struct io_kiocb *req,struct callback_head *cb) +static int io_req_task_work_add (struct io_kiocb *req,struct callback_head *cb, +bool twa_signal_ok) {struct task_struct *tsk = req->task;struct io_ring_ctx *ctx = req->ctx;
@@ -4127,7 +4128,7 @@ static int io_req_task_work_add(struct io_kiocb *req, struct callback_head *cb)* will do the job. */ notify =0 ; -if (!(ctx->flags &IORING_SETUP_SQPOLL )) +if (!(ctx->flags &IORING_SETUP_SQPOLL ) && twa_signal_ok) notify =TWA_SIGNAL ; ret =task_work_add (tsk, cb, notify);
@@ -4141,6 +4142,7 @@ static int __io_async_wake(struct io_kiocb *req, struct io_poll_iocb *poll, __poll_t mask, task_work_func_t func) {struct task_struct *tsk; +bool twa_signal_ok;int ret;/* for instances that support it check for an event match first: */
@@ -4156,13 +4158,21 @@ static int __io_async_wake(struct io_kiocb *req, struct io_poll_iocb *poll,init_task_work (&req->task_work, func);percpu_ref_get (&req->ctx->refs); +/* +* If we using the signalfd wait_queue_head for this wakeup, then +* it's not safe to use TWA_SIGNAL as we could be recursing on the +* tsk->sighand->siglock on doing the wakeup. Should not be needed +* either, as the normal wakeup will suffice. +*/ + twa_signal_ok = (poll->head != &req->task->sighand->signalfd_wqh); +/* * If this fails, then the task is exiting. When a task exits, the * work gets canceled, so just cancel this request as well instead * of executing it. We can't safely execute it anyway, as we may not * have the needed state needed for it anyway. */ - ret =io_req_task_work_add (req, &req->task_work); + ret =io_req_task_work_add (req, &req->task_work, twa_signal_ok);if (unlikely (ret)) {WRITE_ONCE (poll->canceled, true); tsk =io_wq_get_task (req->ctx->io_wq);
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 244/255 io_uring: dont use poll handler if file cant be nonblocking read/written
In reply to Greg Kroah-HartmanFrom: Jens Axboe <[email protected]>
[ Upstream commit 9dab14b81807a40dab8e464ec87043935c562c2c ]
There's no point in using the poll handler if we can't do a nonblocking IO attempt of the operation, since we'll need to go async anyway. In fact this is actively harmful, as reading from eg pipes won't return 0 to indicate EOF.
--- fs/io_uring.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-)
fs/io_uring.c +9 -1
@@ -4503,12 +4503,20 @@ static bool io_arm_poll_handler(struct io_kiocb *req)struct async_poll *apoll;struct io_poll_table ipt;__poll_t mask, ret; +int rw;if (!req->file || !file_can_poll (req->file))return false;if (req->flags & (REQ_F_MUST_PUNT |REQ_F_POLLED ))return false; -if (!def->pollin && !def->pollout) +if (def->pollin) + rw =READ ; +else if (def->pollout) + rw =WRITE ; +else +return false; +/* if we can't nonblock try, then no point in arming a poll handler */ +if (!io_file_supports_async (req->file, rw))return false; apoll =kmalloc (sizeof (*apoll),GFP_ATOMIC );
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 245/255 io_uring: make offset == -1 consistent with preadv2/pwritev2
In reply to Greg Kroah-HartmanFrom: Jens Axboe <[email protected]>
[ Upstream commit 0fef948363f62494d779cf9dc3c0a86ea1e5f7cd ]
The man page for io_uring generally claims were consistent with what preadv2 and pwritev2 accept, but turns out there's a slight discrepancy in how offset == -1 is handled for pipes/streams. preadv doesn't allow it, but preadv2 does. This currently causes io_uring to return -EINVAL if that is attempted, but we should allow that as documented.
This change makes us consistent with preadv2/pwritev2 for just passing in a NULL ppos for streams if the offset is -1.
--- fs/io_uring.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-)
fs/io_uring.c +9 -4
@@ -2518,6 +2518,11 @@ static ssize_t io_import_iovec(int rw, struct io_kiocb *req,return import_iovec (rw, buf, sqe_len,UIO_FASTIOV , iovec, iter); } +static inline loff_t *io_kiocb_ppos (struct kiocb *kiocb) +{ +return kiocb->ki_filp->f_mode &FMODE_STREAM ?NULL : &kiocb->ki_pos; +} +/* * For files that don't have ->read_iter() and ->write_iter(), handle them * by looping over ->read() or ->write() manually.
@@ -2553,10 +2558,10 @@ static ssize_t loop_rw_iter(int rw, struct file *file, struct kiocb *kiocb,if (rw ==READ ) { nr = file->f_op->read (file, iovec.iov_base, - iovec.iov_len, &kiocb->ki_pos); + iovec.iov_len,io_kiocb_ppos (kiocb)); }else { nr = file->f_op->write (file, iovec.iov_base, - iovec.iov_len, &kiocb->ki_pos); + iovec.iov_len,io_kiocb_ppos (kiocb)); }if (iov_iter_is_bvec (iter))
@@ -2681,7 +2686,7 @@ static int io_read(struct io_kiocb *req, bool force_nonblock) goto copy_iov; iov_count =iov_iter_count (&iter); - ret =rw_verify_area (READ , req->file, &kiocb->ki_pos, iov_count); + ret =rw_verify_area (READ , req->file,io_kiocb_ppos (kiocb), iov_count);if (!ret) {ssize_t ret2;
@@ -2780,7 +2785,7 @@ static int io_write(struct io_kiocb *req, bool force_nonblock) goto copy_iov; iov_count =iov_iter_count (&iter); - ret =rw_verify_area (WRITE , req->file, &kiocb->ki_pos, iov_count); + ret =rw_verify_area (WRITE , req->file,io_kiocb_ppos (kiocb), iov_count);if (!ret) {ssize_t ret2;
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 246/255 drm/atomic-helper: reset vblank on crtc reset
In reply to Greg Kroah-HartmanFrom: Daniel Vetter <[email protected]>
[ Upstream commit 51f644b40b4b794b28b982fdd5d0dd8ee63f9272 ]
Only when vblanks are supported ofc.
Some drivers do this already, but most unfortunately missed it. This opens up bugs after driver load, before the crtc is enabled for the first time. syzbot spotted this when loading vkms as a secondary output. Given how many drivers are buggy it's best to solve this once and for all in shared helper code.
Aside from moving the few existing calls to drm_crtc_vblank_reset into helpers (i915 doesn't use helpers, so keeps its own) I think the regression risk is minimal: atomic helpers already rely on drivers calling drm_crtc_vblank_on/off correctly in their hooks when they support vblanks. And driver that's failing to handle vblanks after this is missing those calls already, and vblanks could only work by accident when enabling a CRTC for the first time right after boot.
Big thanks to Tetsuo for helping track down what's going wrong here.
There's only a few drivers which already had the necessary call and needed some updating:
- komeda, atmel and tidss also needed to be changed to call __drm_atomic_helper_crtc_reset() intead of open coding it
- tegra and msm even had it in the same place already, just code motion, and malidp already uses __drm_atomic_helper_crtc_reset().
- Laurent noticed that rcar-du and omap open-code their crtc reset and hence would actually be broken by this patch now. So fix them up by reusing the helpers, which brings the drm_crtc_vblank_reset() back.
Only call left is in i915, which doesn't use drm_mode_config_reset, but has its own fastboot infrastructure. So that's the only case where we actually want this in the driver still.
I've also reviewed all other drivers which set up vblank support with drm_vblank_init. After the previous patch fixing mxsfb all atomic drivers do call drm_crtc_vblank_on/off as they should, the remaining drivers are either legacy kms or legacy dri1 drivers, so not affected by this change to atomic helpers.
v2: Use the drm_dev_has_vblank() helper.
v3: Laurent pointed out that omap and rcar-du used drm_crtc_vblank_off instead of drm_crtc_vblank_reset. Adjust them too.
v4: Laurent noticed that rcar-du and omap open-code their crtc reset and hence would actually be broken by this patch now. So fix them up by reusing the helpers, which brings the drm_crtc_vblank_reset() back.
v5: also mention rcar-du and ompadrm in the proper commit message above (Laurent).
--- drivers/gpu/drm/arm/display/komeda/komeda_crtc.c | 7 ++----- drivers/gpu/drm/arm/malidp_drv.c | 1 - drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c | 7 ++----- drivers/gpu/drm/drm_atomic_state_helper.c | 4 ++++ drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c | 2 -- drivers/gpu/drm/omapdrm/omap_crtc.c | 8 +++++--- drivers/gpu/drm/omapdrm/omap_drv.c | 4 ---- drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 6 +----- drivers/gpu/drm/tegra/dc.c | 1 - drivers/gpu/drm/tidss/tidss_crtc.c | 3 +-- drivers/gpu/drm/tidss/tidss_kms.c | 5 ----- 11 files changed, 15 insertions(+), 33 deletions(-)
drivers/gpu/drm/arm/display/komeda/komeda_crtc.c +2 -5
@@ -492,10 +492,8 @@ static void komeda_crtc_reset(struct drm_crtc *crtc) crtc->state =NULL ; state =kzalloc (sizeof (*state),GFP_KERNEL ); -if (state) { - crtc->state = &state->base; - crtc->state->crtc = crtc; - } +if (state) +__drm_atomic_helper_crtc_reset (crtc, &state->base); } static struct drm_crtc_state *
@@ -616,7 +614,6 @@ static int komeda_crtc_add(struct komeda_kms_dev *kms,return err;drm_crtc_helper_add (crtc, &komeda_crtc_helper_funcs); -drm_crtc_vblank_reset (crtc); crtc->port = kcrtc->master->of_output_port;
drivers/gpu/drm/arm/malidp_drv.c +0 -1
@@ -870,7 +870,6 @@ static int malidp_bind(struct device *dev) drm->irq_enabled = true; ret =drm_vblank_init (drm, drm->mode_config.num_crtc); -drm_crtc_vblank_reset (&malidp->crtc);if (ret <0 ) {DRM_ERROR ("failed to initialise vblank\n" ); goto vblank_fail;
drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c +2 -5
@@ -411,10 +411,8 @@ static void atmel_hlcdc_crtc_reset(struct drm_crtc *crtc) } state =kzalloc (sizeof (*state),GFP_KERNEL ); -if (state) { - crtc->state = &state->base; - crtc->state->crtc = crtc; - } +if (state) +__drm_atomic_helper_crtc_reset (crtc, &state->base); } static struct drm_crtc_state *
@@ -528,7 +526,6 @@ int atmel_hlcdc_crtc_create(struct drm_device *dev) }drm_crtc_helper_add (&crtc->base, &lcdc_crtc_helper_funcs); -drm_crtc_vblank_reset (&crtc->base);drm_mode_crtc_set_gamma_size (&crtc->base,ATMEL_HLCDC_CLUT_SIZE ); drm_crtc_enable_color_mgmt(&crtc->base, 0, false,
drivers/gpu/drm/drm_atomic_state_helper.c +4 -0
@@ -32,6 +32,7 @@#include <drm/drm_device.h> #include <drm/drm_plane.h> #include <drm/drm_print.h> +#include <drm/drm_vblank.h> #include <drm/drm_writeback.h> #include <linux/slab.h>
@@ -93,6 +94,9 @@ __drm_atomic_helper_crtc_reset(struct drm_crtc *crtc,if (crtc_state)__drm_atomic_helper_crtc_state_reset (crtc_state, crtc); +if (drm_dev_has_vblank (crtc->dev)) +drm_crtc_vblank_reset (crtc); + crtc->state = crtc_state; }EXPORT_SYMBOL (__drm_atomic_helper_crtc_reset);
drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c +0 -2
@@ -1117,8 +1117,6 @@ static void mdp5_crtc_reset(struct drm_crtc *crtc)mdp5_crtc_destroy_state (crtc, crtc->state);__drm_atomic_helper_crtc_reset (crtc, &mdp5_cstate->base); - -drm_crtc_vblank_reset (crtc); }static const struct drm_crtc_funcs mdp5_crtc_funcs = {
drivers/gpu/drm/omapdrm/omap_crtc.c +5 -3
@@ -697,14 +697,16 @@ static int omap_crtc_atomic_get_property(struct drm_crtc *crtc,static void omap_crtc_reset (struct drm_crtc *crtc) { +struct omap_crtc_state *state; +if (crtc->state)__drm_atomic_helper_crtc_destroy_state (crtc->state);kfree (crtc->state); - crtc->state =kzalloc (sizeof (struct omap_crtc_state ),GFP_KERNEL ); -if (crtc->state) - crtc->state->crtc = crtc; + state =kzalloc (sizeof (*state),GFP_KERNEL ); +if (state) +__drm_atomic_helper_crtc_reset (crtc, &state->base); } static struct drm_crtc_state *
drivers/gpu/drm/omapdrm/omap_drv.c +0 -4
@@ -595,7 +595,6 @@ static int omapdrm_init(struct omap_drm_private *priv, struct device *dev) {const struct soc_device_attribute *soc;struct drm_device *ddev; -unsigned int i;int ret;DBG ("%s" ,dev_name (dev));
@@ -642,9 +641,6 @@ static int omapdrm_init(struct omap_drm_private *priv, struct device *dev) goto err_cleanup_modeset; } -for (i =0 ; i < priv->num_pipes; i++) -drm_crtc_vblank_off (priv->pipes[i].crtc); -omap_fbdev_init (ddev);drm_kms_helper_poll_init (ddev);
drivers/gpu/drm/rcar-du/rcar_du_crtc.c +1 -5
@@ -975,8 +975,7 @@ static void rcar_du_crtc_reset(struct drm_crtc *crtc) state->crc.source =VSP1_DU_CRC_NONE ; state->crc.index =0 ; - crtc->state = &state->state; - crtc->state->crtc = crtc; +__drm_atomic_helper_crtc_reset (crtc, &state->state); }static int rcar_du_crtc_enable_vblank (struct drm_crtc *crtc)
@@ -1271,9 +1270,6 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int swindex,drm_crtc_helper_add (crtc, &crtc_helper_funcs); -/* Start with vertical blanking interrupt reporting disabled. */ -drm_crtc_vblank_off (crtc); -/* Register the interrupt handler. */ if (rcar_du_has (rcdu,RCAR_DU_FEATURE_CRTC_IRQ_CLOCK )) {/* The IRQ's are associated with the CRTC (sw)index. */
drivers/gpu/drm/tegra/dc.c +0 -1
@@ -1169,7 +1169,6 @@ static void tegra_crtc_reset(struct drm_crtc *crtc)tegra_crtc_atomic_destroy_state (crtc, crtc->state);__drm_atomic_helper_crtc_reset (crtc, &state->base); -drm_crtc_vblank_reset (crtc); } static struct drm_crtc_state *
drivers/gpu/drm/tidss/tidss_crtc.c +1 -2
@@ -352,8 +352,7 @@ static void tidss_crtc_reset(struct drm_crtc *crtc)return ; } - crtc->state = &tcrtc->base; - crtc->state->crtc = crtc; +__drm_atomic_helper_crtc_reset (crtc, &tcrtc->base); }static struct drm_crtc_state *tidss_crtc_duplicate_state (struct drm_crtc *crtc)
drivers/gpu/drm/tidss/tidss_kms.c +0 -5
@@ -253,7 +253,6 @@ static int tidss_dispc_modeset_init(struct tidss_device *tidss)int tidss_modeset_init (struct tidss_device *tidss) {struct drm_device *ddev = &tidss->ddev; -unsigned int i;int ret;dev_dbg (tidss->dev,"%s\n" , __func__);
@@ -278,10 +277,6 @@ int tidss_modeset_init(struct tidss_device *tidss)if (ret)return ret; -/* Start with vertical blanking interrupt reporting disabled. */ -for (i =0 ; i < tidss->num_crtcs; ++i) -drm_crtc_vblank_reset (tidss->crtcs[i]); -drm_mode_config_reset (ddev);dev_dbg (tidss->dev,"%s done\n" , __func__);
Signature · 9 lines
2.25.1 _______________________________________________ linux-arm-kernel mailing list [email protected] http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Greg Kroah-Hartman
maintainerPATCH 247/255 fbmem: pull fbcon_update_vcs() out of fb_set_var()
In reply to Greg Kroah-HartmanFrom: Tetsuo Handa <[email protected]>
[ Upstream commit d88ca7e1a27eb2df056bbf37ddef62e1c73d37ea ]
syzbot is reporting OOB read bug in vc_do_resize() [1] caused by memcpy() based on outdated old_{rows,row_size} values, for resize_screen() can recurse into vc_do_resize() which changes vc->vc_{cols,rows} that outdates old_{rows,row_size} values which were saved before calling resize_screen().
Daniel Vetter explained that resize_screen() should not recurse into fbcon_update_vcs() path due to FBINFO_MISC_USEREVENT being still set when calling resize_screen().
Instead of masking FBINFO_MISC_USEREVENT before calling fbcon_update_vcs(), we can remove FBINFO_MISC_USEREVENT by calling fbcon_update_vcs() only if fb_set_var() returned 0. This change assumes that it is harmless to call fbcon_update_vcs() when fb_set_var() returned 0 without reaching fb_notifier_call_chain().
[1] https://syzkaller.appspot.com/bug?id=c70c88cfd16dcf6e1d3c7f0ab8648b3144b5b25e
--- drivers/video/fbdev/core/fbmem.c | 8 ++------ drivers/video/fbdev/core/fbsysfs.c | 4 ++-- drivers/video/fbdev/ps3fb.c | 5 +++-- include/linux/fb.h | 2 -- 4 files changed, 7 insertions(+), 12 deletions(-)
drivers/video/fbdev/core/fbmem.c +2 -6
@@ -957,7 +957,6 @@ static int fb_check_caps(struct fb_info *info, struct fb_var_screeninfo *var,int fb_set_var (struct fb_info *info,struct fb_var_screeninfo *var) { -int flags = info->flags;int ret =0 ;u32 activate;struct fb_var_screeninfo old_var;
@@ -1052,9 +1051,6 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var) event.data = &mode;fb_notifier_call_chain (FB_EVENT_MODE_CHANGE , &event); -if (flags &FBINFO_MISC_USEREVENT ) -fbcon_update_vcs (info, activate &FB_ACTIVATE_ALL ); -return 0 ; }EXPORT_SYMBOL (fb_set_var);
@@ -1105,9 +1101,9 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd,return -EFAULT ;console_lock ();lock_fb_info (info); - info->flags |=FBINFO_MISC_USEREVENT ; ret =fb_set_var (info, &var); - info->flags &= ~FBINFO_MISC_USEREVENT ; +if (!ret) +fbcon_update_vcs (info, var.activate &FB_ACTIVATE_ALL );unlock_fb_info (info);console_unlock ();if (!ret &©_to_user (argp, &var,sizeof (var)))
drivers/video/fbdev/core/fbsysfs.c +2 -2
@@ -91,9 +91,9 @@ static int activate(struct fb_info *fb_info, struct fb_var_screeninfo *var) var->activate |=FB_ACTIVATE_FORCE ;console_lock (); - fb_info->flags |=FBINFO_MISC_USEREVENT ; err =fb_set_var (fb_info, var); - fb_info->flags &= ~FBINFO_MISC_USEREVENT ; +if (!err) +fbcon_update_vcs (fb_info, var->activate &FB_ACTIVATE_ALL );console_unlock ();if (err)return err;
drivers/video/fbdev/ps3fb.c +3 -2
@@ -29,6 +29,7 @@#include <linux/freezer.h> #include <linux/uaccess.h> #include <linux/fb.h> +#include <linux/fbcon.h> #include <linux/init.h> #include <asm/cell-regs.h>
@@ -824,12 +825,12 @@ static int ps3fb_ioctl(struct fb_info *info, unsigned int cmd, var = info->var;fb_videomode_to_var (&var, vmode);console_lock (); - info->flags |=FBINFO_MISC_USEREVENT ;/* Force, in case only special bits changed */ var.activate |=FB_ACTIVATE_FORCE ; par->new_mode_id = val; retval =fb_set_var (info, &var); - info->flags &= ~FBINFO_MISC_USEREVENT ; +if (!retval) +fbcon_update_vcs (info, var.activate &FB_ACTIVATE_ALL );console_unlock (); }break ;
include/linux/fb.h +0 -2
@@ -400,8 +400,6 @@ struct fb_tile_ops {#define FBINFO_HWACCEL_YPAN 0x2000/* optional */ #define FBINFO_HWACCEL_YWRAP 0x4000/* optional */ -#define FBINFO_MISC_USEREVENT 0x10000/* event request -from userspace */ #define FBINFO_MISC_TILEBLITTING 0x20000/* use tile blitting */ /* A driver may set this flag to indicate that it does want a set_par to be
Signature · 1 line
2.25.1
Greg Kroah-Hartman
maintainerPATCH 248/255 mm/page_counter: fix various data races at memsw
In reply to Greg Kroah-HartmanFrom: Qian Cai <[email protected]>
commit 6e4bd50f3888fa8fea8bc66a0ad4ad5f1c862961 upstream.
Commit 3e32cb2e0a12 ("mm: memcontrol: lockless page counters") could had memcg->memsw->watermark and memcg->memsw->failcnt been accessed concurrently as reported by KCSAN,
BUG: KCSAN: data-race in page_counter_try_charge / page_counter_try_charge
read to 0xffff8fb18c4cd190 of 8 bytes by task 1081 on cpu 59:
page_counter_try_charge+0x4d/0x150 mm/page_counter.c:138 try_charge+0x131/0xd50 mm/memcontrol.c:2405 __memcg_kmem_charge_memcg+0x58/0x140 __memcg_kmem_charge+0xcc/0x280 __alloc_pages_nodemask+0x1e1/0x450 alloc_pages_current+0xa6/0x120 pte_alloc_one+0x17/0xd0 __pte_alloc+0x3a/0x1f0 copy_p4d_range+0xc36/0x1990 copy_page_range+0x21d/0x360 dup_mmap+0x5f5/0x7a0 dup_mm+0xa2/0x240 copy_process+0x1b3f/0x3460 _do_fork+0xaa/0xa20 __x64_sys_clone+0x13b/0x170 do_syscall_64+0x91/0xb47 entry_SYSCALL_64_after_hwframe+0x49/0xbe
write to 0xffff8fb18c4cd190 of 8 bytes by task 1153 on cpu 120:
page_counter_try_charge+0x5b/0x150 mm/page_counter.c:139 try_charge+0x131/0xd50 mm/memcontrol.c:2405 mem_cgroup_try_charge+0x159/0x460 mem_cgroup_try_charge_delay+0x3d/0xa0 wp_page_copy+0x14d/0x930 do_wp_page+0x107/0x7b0 __handle_mm_fault+0xce6/0xd40 handle_mm_fault+0xfc/0x2f0 do_page_fault+0x263/0x6f9 page_fault+0x34/0x40 BUG: KCSAN: data-race in page_counter_try_charge / page_counter_try_charge
write to 0xffff88809bbf2158 of 8 bytes by task 11782 on cpu 0:
page_counter_try_charge+0x100/0x170 mm/page_counter.c:129 try_charge+0x185/0xbf0 mm/memcontrol.c:2405 __memcg_kmem_charge_memcg+0x4a/0xe0 mm/memcontrol.c:2837 __memcg_kmem_charge+0xcf/0x1b0 mm/memcontrol.c:2877 __alloc_pages_nodemask+0x26c/0x310 mm/page_alloc.c:4780
read to 0xffff88809bbf2158 of 8 bytes by task 11814 on cpu 1:
page_counter_try_charge+0xef/0x170 mm/page_counter.c:129 try_charge+0x185/0xbf0 mm/memcontrol.c:2405 __memcg_kmem_charge_memcg+0x4a/0xe0 mm/memcontrol.c:2837 __memcg_kmem_charge+0xcf/0x1b0 mm/memcontrol.c:2877 __alloc_pages_nodemask+0x26c/0x310 mm/page_alloc.c:4780
Since watermark could be compared or set to garbage due to a data race which would change the code logic, fix it by adding a pair of READ_ONCE() and WRITE_ONCE() in those places.
The "failcnt" counter is tolerant of some degree of inaccuracy and is only used to report stats, a data race will not be harmful, thus mark it as an intentional data race using the data_race() macro.
--- mm/page_counter.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-)
mm/page_counter.c +7 -6
@@ -77,8 +77,8 @@ void page_counter_charge(struct page_cou* This is indeed racy, but we can live with some * inaccuracy in the watermark. */ -if (new > c->watermark) - c->watermark = new; +if (new >READ_ONCE (c->watermark)) +WRITE_ONCE (c->watermark, new); } }
@@ -119,9 +119,10 @@ bool page_counter_try_charge(struct pagepropagate_protected_usage (c, new);/* * This is racy, but we can live with some -* inaccuracy in the failcnt. +* inaccuracy in the failcnt which is only used +* to report stats. */ - c->failcnt++; +data_race (c->failcnt++); *fail = c; goto failed; }
@@ -130,8 +131,8 @@ bool page_counter_try_charge(struct page* Just like with failcnt, we can live with some * inaccuracy in the watermark. */ -if (new > c->watermark) - c->watermark = new; +if (new >READ_ONCE (c->watermark)) +WRITE_ONCE (c->watermark, new); }return true;
Greg Kroah-Hartman
maintainerPATCH 249/255 HID: hiddev: Fix slab-out-of-bounds write in hiddev_ioctl_usage()
In reply to Greg Kroah-HartmanFrom: Peilin Ye <[email protected]>
commit 25a097f5204675550afb879ee18238ca917cba7a upstream.
uref->usage_index is not always being properly checked, causing hiddev_ioctl_usage() to go out of bounds under some cases. Fix it.
--- drivers/hid/usbhid/hiddev.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/hid/usbhid/hiddev.c +4 -0
@@ -519,12 +519,16 @@ static noinline int hiddev_ioctl_usage(sswitch (cmd) {case HIDIOCGUSAGE : +if (uref->usage_index >= field->report_count) + goto inval; uref->value = field->value[uref->usage_index];if (copy_to_user (user_arg, uref,sizeof (*uref))) goto fault; goto goodreturn;case HIDIOCSUSAGE : +if (uref->usage_index >= field->report_count) + goto inval; field->value[uref->usage_index] = uref->value; goto goodreturn;
Greg Kroah-Hartman
maintainerPATCH 250/255 drm/vmwgfx/stdu: Use drm_mode_config_reset
In reply to Greg Kroah-HartmanFrom: Daniel Vetter <[email protected]>
commit 68745d1edf1700a668c15ecbed466d18f14c7e9b upstream.
When converting to atomic the state reset was done by directly calling the functions, and before the modeset object was fully initialized. This means the various ->dev pointers weren't set up.
After
commit 51f644b40b4b794b28b982fdd5d0dd8ee63f9272
Author: Daniel Vetter <[email protected]> Date: Fri Jun 12 18:00:49 2020 +0200
drm/atomic-helper: reset vblank on crtc reset
this started to oops because now we're trying to derefence drm_crtc->dev. Fix this up by entirely switching over to drm_mode_config_reset, called once everything is set up.
--- drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-)
drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c +2 -7
@@ -1738,8 +1738,6 @@ static int vmw_stdu_init(struct vmw_priv stdu->base.is_implicit = false;/* Initialize primary plane */ -vmw_du_plane_reset (primary); - ret = drm_universal_plane_init(dev, primary, 0, &vmw_stdu_plane_funcs, vmw_primary_plane_formats,
@@ -1754,8 +1752,6 @@ static int vmw_stdu_init(struct vmw_privdrm_plane_enable_fb_damage_clips (primary);/* Initialize cursor plane */ -vmw_du_plane_reset (cursor); - ret = drm_universal_plane_init(dev, cursor, 0, &vmw_stdu_cursor_funcs, vmw_cursor_plane_formats,
@@ -1769,8 +1765,6 @@ static int vmw_stdu_init(struct vmw_privdrm_plane_helper_add (cursor, &vmw_stdu_cursor_plane_helper_funcs); -vmw_du_connector_reset (connector); - ret =drm_connector_init (dev, connector, &vmw_stdu_connector_funcs,DRM_MODE_CONNECTOR_VIRTUAL );if (ret) {
@@ -1798,7 +1792,6 @@ static int vmw_stdu_init(struct vmw_priv goto err_free_encoder; } -vmw_du_crtc_reset (crtc); ret =drm_crtc_init_with_planes (dev, crtc, &stdu->base.primary, &stdu->base.cursor, &vmw_stdu_crtc_funcs,NULL );
@@ -1894,6 +1887,8 @@ int vmw_kms_stdu_init_display(struct vmw } } +drm_mode_config_reset (dev); +DRM_INFO ("Screen Target Display device initialized\n" );return 0 ;
Greg Kroah-Hartman
maintainerPATCH 251/255 drm/vmwgfx/sou: Use drm_mode_config_reset
In reply to Greg Kroah-HartmanFrom: Roland Scheidegger <[email protected]>
commit 1338441cf166e2ef789af5915b961d4e13a4ec31 upstream.
Same problem as in stdu, same fix.
--- drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-)
drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c +2 -7
@@ -859,8 +859,6 @@ static int vmw_sou_init(struct vmw_priva sou->base.is_implicit = false;/* Initialize primary plane */ -vmw_du_plane_reset (primary); - ret = drm_universal_plane_init(dev, &sou->base.primary, 0, &vmw_sou_plane_funcs, vmw_primary_plane_formats,
@@ -875,8 +873,6 @@ static int vmw_sou_init(struct vmw_privadrm_plane_enable_fb_damage_clips (primary);/* Initialize cursor plane */ -vmw_du_plane_reset (cursor); - ret = drm_universal_plane_init(dev, &sou->base.cursor, 0, &vmw_sou_cursor_funcs, vmw_cursor_plane_formats,
@@ -890,7 +886,6 @@ static int vmw_sou_init(struct vmw_privadrm_plane_helper_add (cursor, &vmw_sou_cursor_plane_helper_funcs); -vmw_du_connector_reset (connector); ret =drm_connector_init (dev, connector, &vmw_sou_connector_funcs,DRM_MODE_CONNECTOR_VIRTUAL );if (ret) {
@@ -918,8 +913,6 @@ static int vmw_sou_init(struct vmw_priva goto err_free_encoder; } - -vmw_du_crtc_reset (crtc); ret =drm_crtc_init_with_planes (dev, crtc, &sou->base.primary, &sou->base.cursor, &vmw_screen_object_crtc_funcs,NULL );
@@ -973,6 +966,8 @@ int vmw_kms_sou_init_display(struct vmw_ dev_priv->active_display_unit = vmw_du_screen_object; +drm_mode_config_reset (dev); +DRM_INFO ("Screen Objects Display Unit initialized\n" );return 0 ;
Greg Kroah-Hartman
maintainerPATCH 252/255 drm/vmwgfx/ldu: Use drm_mode_config_reset
In reply to Greg Kroah-HartmanFrom: Roland Scheidegger <[email protected]>
commit 981243371a5d832af5bc572071172e955d02fe88 upstream.
Same problem as in stdu, same fix.
--- drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-)
drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c +2 -6
@@ -387,8 +387,6 @@ static int vmw_ldu_init(struct vmw_priva ldu->base.is_implicit = true;/* Initialize primary plane */ -vmw_du_plane_reset (primary); - ret = drm_universal_plane_init(dev, &ldu->base.primary, 0, &vmw_ldu_plane_funcs, vmw_primary_plane_formats,
@@ -402,8 +400,6 @@ static int vmw_ldu_init(struct vmw_privadrm_plane_helper_add (primary, &vmw_ldu_primary_plane_helper_funcs);/* Initialize cursor plane */ -vmw_du_plane_reset (cursor); - ret = drm_universal_plane_init(dev, &ldu->base.cursor, 0, &vmw_ldu_cursor_funcs, vmw_cursor_plane_formats,
@@ -417,7 +413,6 @@ static int vmw_ldu_init(struct vmw_privadrm_plane_helper_add (cursor, &vmw_ldu_cursor_plane_helper_funcs); -vmw_du_connector_reset (connector); ret =drm_connector_init (dev, connector, &vmw_legacy_connector_funcs,DRM_MODE_CONNECTOR_VIRTUAL );if (ret) {
@@ -445,7 +440,6 @@ static int vmw_ldu_init(struct vmw_priva goto err_free_encoder; } -vmw_du_crtc_reset (crtc); ret =drm_crtc_init_with_planes (dev, crtc, &ldu->base.primary, &ldu->base.cursor, &vmw_legacy_crtc_funcs,NULL );
@@ -520,6 +514,8 @@ int vmw_kms_ldu_init_display(struct vmw_ dev_priv->active_display_unit = vmw_du_legacy; +drm_mode_config_reset (dev); +DRM_INFO ("Legacy Display Unit initialized\n" );return 0 ;
Greg Kroah-Hartman
maintainerPATCH 253/255 libbpf: Fix build on ppc64le architecture
In reply to Greg Kroah-HartmanFrom: Andrii Nakryiko <[email protected]>
commit 3fb1a96a91120877488071a167d26d76be4be977 upstream.
On ppc64le we get the following warning:
In file included from btf_dump.c:16:0:
btf_dump.c: In function ‘btf_dump_emit_struct_def’:
../include/linux/kernel.h:20:17: error: comparison of distinct pointer types lacks a cast [-Werror]
(void) (&_max1 == &_max2); \
^
btf_dump.c:882:11: note: in expansion of macro ‘max’
m_sz = max(0LL, btf__resolve_size(d->btf, m->type));
^~~Fix by explicitly casting to __s64, which is a return type from btf__resolve_size().
--- tools/lib/bpf/btf_dump.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/lib/bpf/btf_dump.c +1 -1
@@ -876,7 +876,7 @@ static void btf_dump_emit_struct_def(strbtf_dump_printf (d,": %d" , m_sz); off = m_off + m_sz; }else { - m_sz =max (0LL ,btf__resolve_size (d->btf, m->type)); + m_sz =max ((__s64 )0 ,btf__resolve_size (d->btf, m->type)); off = m_off + m_sz *8 ; }btf_dump_printf (d,";" );
Greg Kroah-Hartman
maintainerPATCH 254/255 dma-pool: Fix an uninitialized variable bug in atomic_pool_expand()
In reply to Greg Kroah-HartmanFrom: Dan Carpenter <[email protected]>
commit 892fc9f6835ecf075efac20789b012c5c9997fcc upstream.
The "page" pointer can be used with out being initialized.
--- kernel/dma/pool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/dma/pool.c +1 -1
@@ -84,7 +84,7 @@ static int atomic_pool_expand(struct gen gfp_t gfp) {unsigned int order; -struct page *page; +struct page *page =NULL ;void *addr;int ret = -ENOMEM ;
Greg Kroah-Hartman
maintainerPATCH 255/255 ALSA: usb-audio: Update documentation comment for MS2109 quirk
In reply to Greg Kroah-HartmanFrom: Hector Martin <[email protected]>
commit 74a2a7de81a2ef20732ec02087314e92692a7a1b upstream.
As the recent fix addressed the channel swap problem more properly, update the comment as well.
--- sound/usb/quirks-table.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
sound/usb/quirks-table.h +2 -2
@@ -3727,8 +3727,8 @@ ALC1220_VB_DESKTOP(0x26ce, 0x0a01), /* A* they pretend to be 96kHz mono as a workaround for stereo being broken * by that... * -* They also have swapped L-R channels, but that's for userspace to deal -* with. +* They also have an issue with initial stream alignment that causes the +* channels to be swapped and out of phase, which is dealt with in quirks.c. */ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
Quoted 1 line · Greg Kroah-Hartman
This is the start of the stable review cycle for the 5.8.6 release.
This one has a bunch of things I care about, so I gave it a try on both my server & desktop (Gentoo, x86_64). Applies & builds cleanly, everything working fine: no spontaneous fires or unexpected screams from the underworld.
Cheers!
Holger
Greg Kroah-Hartman
maintainerQuoted 7 lines · Holger Hoffstätte
Quoted 1 line · Greg Kroah-Hartman
This is the start of the stable review cycle for the 5.8.6 release.
This one has a bunch of things I care about, so I gave it a try on both my server & desktop (Gentoo,
x86_64). Applies & builds cleanly, everything working fine: no spontaneous fires or unexpected screams from the underworld.
Wonderful, glad the underworld is happy with this release :)
Thanks for testing,
greg k-h
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 5.8.6 release. There are 255 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Thu, 03 Sep 2020 15:09:01 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 9 lines
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.8.6-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-5.8.y
and the diffstat can be found below.thanks,
greg k-h
Compiled and booted on my test system. No dmesg regressions.
thanks,
-- Shuah
Greg Kroah-Hartman
maintainerQuoted 15 lines · Shuah Khan
Quoted 14 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 5.8.6 release. There are 255 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Thu, 03 Sep 2020 15:09:01 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.8.6-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-5.8.y
and the diffstat can be found below.
Quoted 8 lines
Quoted 4 lines
thanks,
greg k-h
Compiled and booted on my test system. No dmesg regressions.
Tested-by Shuah Khan <[email protected]>
Thanks for testing all of these and letting me know.
greg k-h
Quoted 10 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 5.8.6 release. There are 255 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Thu, 03 Sep 2020 15:09:01 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 9 lines
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.8.6-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-5.8.y
and the diffstat can be found below.thanks,
greg k-h
While running LTP CVE test suite on i386 this BUG triggered after the known warning. Please find below full test log link [1]. This was reported on the mailing list on next-20200811 but did not get any reply [2].
[ 138.177043] ------------[ cut here ]------------ [ 138.181675] WARNING: CPU: 1 PID: 8301 at mm/mremap.c:230 move_page_tables+0x6ef/0x720 [ 138.189515] Modules linked in: x86_pkg_temp_thermal [ 138.194436] CPU: 1 PID: 8301 Comm: true Not tainted 5.8.6-rc1 #1 [ 138.194437] Hardware name: Supermicro SYS-5019S-ML/X11SSH-F, BIOS 2.2 05/23/2018 [ 138.194439] EIP: move_page_tables+0x6ef/0x720
<>
[ 802.156512] BUG: unable to handle page fault for address: fe402000 [ 802.162703] #PF: supervisor write access in kernel mode [ 802.167927] #PF: error_code(0x0002) - not-present page [ 802.173064] *pde = 23e61067 *pte = 64b32163 [ 802.177329] Oops: 0002 [#1] SMP [ 802.180469] CPU: 1 PID: 13118 Comm: cve-2017-17053 Tainted: G W 5.8.6-rc1 #1 [ 802.188811] Hardware name: Supermicro SYS-5019S-ML/X11SSH-F, BIOS 2.2 05/23/2018 [ 802.196199] EIP: memcpy+0x14/0x30 [ 802.199517] Code: e8 a1 72 c5 ff 0f 31 31 c3 59 58 eb 85 cc cc cc cc cc cc cc cc cc 3e 8d 74 26 00 55 89 e5 57 89 c7 56 89 d6 53 89 cb c1 e9 02 <f3> a5 89 d9 83 e1 03 74 02 f3 a4 5b 5e 5f 5d c3 8d b4 26 00 00 00 [ 802.218259] EAX: fe402000 EBX: 00010000 ECX: 00004000 EDX: fb3dd000 [ 802.224518] ESI: fb3dd000 EDI: fe402000 EBP: ea799ddc ESP: ea799dd0 [ 802.230773] DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068 EFLAGS: 00010206 [ 802.237551] CR0: 80050033 CR2: fe402000 CR3: 1eee9000 CR4: 003406d0 [ 802.243809] DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000 [ 802.250065] DR6: fffe0ff0 DR7: 00000400 [ 802.253897] Call Trace: [ 802.256345] ldt_dup_context+0x6b/0x90 [ 802.260093] dup_mm+0x2b3/0x480 [ 802.263230] copy_process+0x13d6/0x1650 [ 802.267062] _do_fork+0x7b/0x3b0 [ 802.270284] ? set_next_entity+0xa9/0x250 [ 802.274290] __ia32_sys_clone+0x77/0xa0 [ 802.278119] do_syscall_32_irqs_on+0x3d/0x250 [ 802.282472] ? do_fast_syscall_32+0x2d/0xc0 [ 802.286656] ? trace_hardirqs_on+0x30/0xf0 [ 802.290746] ? trace_hardirqs_off_finish+0x32/0xa0 [ 802.295533] ? do_SYSENTER_32+0x15/0x20 [ 802.299371] do_fast_syscall_32+0x49/0xc0 [ 802.303374] do_SYSENTER_32+0x15/0x20 [ 802.307032] entry_SYSENTER_32+0x9f/0xf2 [ 802.310956] EIP: 0xb7fbb549 [ 802.313747] Code: 03 74 c0 01 10 05 03 74 b8 01 10 06 03 74 b4 01 10 07 03 74 b0 01 10 08 03 74 d8 01 00 00 00 00 00 51 52 55 89 e5 0f 34 cd 80 <5d> 5a 59 c3 90 90 90 90 8d 76 00 58 b8 77 00 00 00 cd 80 90 8d 76 [ 802.332483] EAX: ffffffda EBX: 01200011 ECX: 00000000 EDX: 00000000 [ 802.338742] ESI: 00000000 EDI: b7dbdba8 EBP: b7dbd348 ESP: b7dbd2f0 [ 802.344998] DS: 007b ES: 007b FS: 0000 GS: 0033 SS: 007b EFLAGS: 00000246 [ 802.351776] Modules linked in: algif_hash x86_pkg_temp_thermal [ 802.357608] CR2: 00000000fe402000 [ 802.360920] ---[ end trace ea48459ba50c2a87 ]--- [ 802.365542] EIP: memcpy+0x14/0x30 [ 802.368858] Code: e8 a1 72 c5 ff 0f 31 31 c3 59 58 eb 85 cc cc cc cc cc cc cc cc cc 3e 8d 74 26 00 55 89 e5 57 89 c7 56 89 d6 53 89 cb c1 e9 02 <f3> a5 89 d9 83 e1 03 74 02 f3 a4 5b 5e 5f 5d c3 8d b4 26 00 00 00 [ 802.387593] EAX: fe402000 EBX: 00010000 ECX: 00004000 EDX: fb3dd000 [ 802.393852] ESI: fb3dd000 EDI: fe402000 EBP: ea799ddc ESP: ea799dd0 [ 802.400107] DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068 EFLAGS: 00010206 [ 802.406887] CR0: 80050033 CR2: fe402000 CR3: 1eee9000 CR4: 003406d0 [ 802.413143] DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000 [ 802.419400] DR6: fffe0ff0 DR7: 00000400
full test log,
[1] https://qa-reports.linaro.org/lkft/linux-stable-rc-5.8-oe/build/v5.8.5-256-gad57c5b5e64d/testrun/3148295/suite/linux-log-parser/test/check-kernel-bug-1727425/log
[2] https://lore.kernel.org/linux-mm/CA+G9fYsiNgoh09h0paf1+UTKhPnn490QCoLB2dRFhMT+Cjh9RA@mail.gmail.com/
--
Linaro LKFT
https://lkft.linaro.org
Greg Kroah-Hartman
maintainerQuoted 96 lines · Naresh Kamboju
Quoted 10 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 5.8.6 release. There are 255 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Thu, 03 Sep 2020 15:09:01 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 9 lines
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.8.6-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-5.8.y
and the diffstat can be found below.thanks,
greg k-h
While running LTP CVE test suite on i386 this BUG triggered after the known warning. Please find below full test log link [1]. This was reported on the mailing list on next-20200811 but did not get any reply [2].
[ 138.177043] ------------[ cut here ]------------ [ 138.181675] WARNING: CPU: 1 PID: 8301 at mm/mremap.c:230 move_page_tables+0x6ef/0x720 [ 138.189515] Modules linked in: x86_pkg_temp_thermal [ 138.194436] CPU: 1 PID: 8301 Comm: true Not tainted 5.8.6-rc1 #1 [ 138.194437] Hardware name: Supermicro SYS-5019S-ML/X11SSH-F, BIOS 2.2 05/23/2018 [ 138.194439] EIP: move_page_tables+0x6ef/0x720<>
[ 802.156512] BUG: unable to handle page fault for address: fe402000 [ 802.162703] #PF: supervisor write access in kernel mode [ 802.167927] #PF: error_code(0x0002) - not-present page [ 802.173064] *pde = 23e61067 *pte = 64b32163 [ 802.177329] Oops: 0002 [#1] SMP [ 802.180469] CPU: 1 PID: 13118 Comm: cve-2017-17053 Tainted: G W 5.8.6-rc1 #1 [ 802.188811] Hardware name: Supermicro SYS-5019S-ML/X11SSH-F, BIOS 2.2 05/23/2018 [ 802.196199] EIP: memcpy+0x14/0x30 [ 802.199517] Code: e8 a1 72 c5 ff 0f 31 31 c3 59 58 eb 85 cc cc cc cc cc cc cc cc cc 3e 8d 74 26 00 55 89 e5 57 89 c7 56 89 d6 53 89 cb c1 e9 02 <f3> a5 89 d9 83 e1 03 74 02 f3 a4 5b 5e 5f 5d c3 8d b4 26 00 00 00 [ 802.218259] EAX: fe402000 EBX: 00010000 ECX: 00004000 EDX: fb3dd000 [ 802.224518] ESI: fb3dd000 EDI: fe402000 EBP: ea799ddc ESP: ea799dd0 [ 802.230773] DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068 EFLAGS: 00010206 [ 802.237551] CR0: 80050033 CR2: fe402000 CR3: 1eee9000 CR4: 003406d0 [ 802.243809] DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000 [ 802.250065] DR6: fffe0ff0 DR7: 00000400 [ 802.253897] Call Trace: [ 802.256345] ldt_dup_context+0x6b/0x90 [ 802.260093] dup_mm+0x2b3/0x480 [ 802.263230] copy_process+0x13d6/0x1650 [ 802.267062] _do_fork+0x7b/0x3b0 [ 802.270284] ? set_next_entity+0xa9/0x250 [ 802.274290] __ia32_sys_clone+0x77/0xa0 [ 802.278119] do_syscall_32_irqs_on+0x3d/0x250 [ 802.282472] ? do_fast_syscall_32+0x2d/0xc0 [ 802.286656] ? trace_hardirqs_on+0x30/0xf0 [ 802.290746] ? trace_hardirqs_off_finish+0x32/0xa0 [ 802.295533] ? do_SYSENTER_32+0x15/0x20 [ 802.299371] do_fast_syscall_32+0x49/0xc0 [ 802.303374] do_SYSENTER_32+0x15/0x20 [ 802.307032] entry_SYSENTER_32+0x9f/0xf2 [ 802.310956] EIP: 0xb7fbb549 [ 802.313747] Code: 03 74 c0 01 10 05 03 74 b8 01 10 06 03 74 b4 01 10 07 03 74 b0 01 10 08 03 74 d8 01 00 00 00 00 00 51 52 55 89 e5 0f 34 cd 80 <5d> 5a 59 c3 90 90 90 90 8d 76 00 58 b8 77 00 00 00 cd 80 90 8d 76 [ 802.332483] EAX: ffffffda EBX: 01200011 ECX: 00000000 EDX: 00000000 [ 802.338742] ESI: 00000000 EDI: b7dbdba8 EBP: b7dbd348 ESP: b7dbd2f0 [ 802.344998] DS: 007b ES: 007b FS: 0000 GS: 0033 SS: 007b EFLAGS: 00000246 [ 802.351776] Modules linked in: algif_hash x86_pkg_temp_thermal [ 802.357608] CR2: 00000000fe402000 [ 802.360920] ---[ end trace ea48459ba50c2a87 ]--- [ 802.365542] EIP: memcpy+0x14/0x30 [ 802.368858] Code: e8 a1 72 c5 ff 0f 31 31 c3 59 58 eb 85 cc cc cc cc cc cc cc cc cc 3e 8d 74 26 00 55 89 e5 57 89 c7 56 89 d6 53 89 cb c1 e9 02 <f3> a5 89 d9 83 e1 03 74 02 f3 a4 5b 5e 5f 5d c3 8d b4 26 00 00 00 [ 802.387593] EAX: fe402000 EBX: 00010000 ECX: 00004000 EDX: fb3dd000 [ 802.393852] ESI: fb3dd000 EDI: fe402000 EBP: ea799ddc ESP: ea799dd0 [ 802.400107] DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068 EFLAGS: 00010206 [ 802.406887] CR0: 80050033 CR2: fe402000 CR3: 1eee9000 CR4: 003406d0 [ 802.413143] DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000 [ 802.419400] DR6: fffe0ff0 DR7: 00000400
Quoted 4 lines
full test log,
[1] https://qa-reports.linaro.org/lkft/linux-stable-rc-5.8-oe/build/v5.8.5-256-gad57c5b5e64d/testrun/3148295/suite/linux-log-parser/test/check-kernel-bug-1727425/log[2] https://lore.kernel.org/linux-mm/CA+G9fYsiNgoh09h0paf1+UTKhPnn490QCoLB2dRFhMT+Cjh9RA@mail.gmail.com/
As this also triggers on mainline/Linus's tree, I'll just let it be for now, thanks!
greg k-h