ACPI: processor idle: Fix up C-state latency if not ordered
Subsystems (4)
Sasha Levin
maintainerPATCH 1/9 ACPI: processor idle: Fix up C-state latency if not ordered
From: Mario Limonciello <[email protected]>
[ Upstream commit 65ea8f2c6e230bdf71fed0137cf9e9d1b307db32 ]
Generally, the C-state latency is provided by the _CST method or FADT, but some OEM platforms using AMD Picasso, Renoir, Van Gogh, and Cezanne set the C2 latency greater than C3's which causes the C2 state to be skipped.
That will block the core entering PC6, which prevents S0ix working properly on Linux systems.
In other operating systems, the latency values are not validated and this does not cause problems by skipping states.
To avoid this issue on Linux, detect when latencies are not an arithmetic progression and sort them.
--- drivers/acpi/processor_idle.c | 40 +++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+)
drivers/acpi/processor_idle.c +40 -0
@@ -29,6 +29,7 @@#include <linux/acpi.h> #include <linux/dmi.h> #include <linux/sched.h> /* need_resched() */ +#include <linux/sort.h> #include <linux/tick.h> #include <linux/cpuidle.h> #include <linux/cpu.h>
@@ -538,10 +539,37 @@ static void acpi_processor_power_verify_c3(struct acpi_processor *pr,return ; } +static int acpi_cst_latency_cmp (const void *a,const void *b) +{ +const struct acpi_processor_cx *x = a, *y = b; + +if (!(x->valid && y->valid)) +return 0 ; +if (x->latency > y->latency) +return 1 ; +if (x->latency < y->latency) +return -1 ; +return 0 ; +} +static void acpi_cst_latency_swap (void *a,void *b,int n) +{ +struct acpi_processor_cx *x = a, *y = b; +u32 tmp; + +if (!(x->valid && y->valid)) +return ; + tmp = x->latency; + x->latency = y->latency; + y->latency = tmp; +} +static int acpi_processor_power_verify (struct acpi_processor *pr) {unsigned int i;unsigned int working =0 ; +unsigned int last_latency =0 ; +unsigned int last_type =0 ; +bool buggy_latency = false; pr->power.timer_broadcast_on_state =INT_MAX ;
@@ -565,12 +593,24 @@ static int acpi_processor_power_verify(struct acpi_processor *pr) }if (!cx->valid)continue ; +if (cx->type >= last_type && cx->latency < last_latency) + buggy_latency = true; + last_latency = cx->latency; + last_type = cx->type;lapic_timer_check_state (i, pr, cx);tsc_check_state (cx->type); working++; } +if (buggy_latency) { +pr_notice ("FW issue: working around C-state latencies out of order\n" ); +sort (&pr->power.states[1 ], max_cstate, +sizeof (struct acpi_processor_cx ), + acpi_cst_latency_cmp, + acpi_cst_latency_swap); + } +lapic_timer_propagate_broadcast (pr);return (working);
Signature · 1 line
2.30.2
Sasha Levin
maintainerPATCH 2/9 block_dump: remove block_dump feature in mark_inode_dirty()
From: "zhangyi (F)" <[email protected]>
[ Upstream commit 12e0613715e1cf305fffafaf0e89d810d9a85cc0 ]
block_dump is an old debugging interface, one of it's functions is used to print the information about who write which file on disk. If we enable block_dump through /proc/sys/vm/block_dump and turn on debug log level, we can gather information about write process name, target file name and disk from kernel message. This feature is realized in block_dump___mark_inode_dirty(), it print above information into kernel message directly when marking inode dirty, so it is noisy and can easily trigger log storm. At the same time, get the dentry refcount is also not safe, we found it will lead to deadlock on ext4 file system with data=journal mode.
After tracepoints has been introduced into the kernel, we got a tracepoint in __mark_inode_dirty(), which is a better replacement of block_dump___mark_inode_dirty(). The only downside is that it only trace the inode number and not a file name, but it probably doesn't matter because the original printed file name in block_dump is not accurate in some cases, and we can still find it through the inode number and device id. So this patch delete the dirting inode part of block_dump feature.
--- fs/fs-writeback.c | 25 ------------------------- 1 file changed, 25 deletions(-)
fs/fs-writeback.c +0 -25
@@ -2088,28 +2088,6 @@ int dirtytime_interval_handler(struct ctl_table *table, int write,return ret; } -static noinline void block_dump___mark_inode_dirty(struct inode *inode) -{ -if (inode->i_ino ||strcmp (inode->i_sb->s_id,"bdev" )) { -struct dentry *dentry; -const char *name ="?" ; - - dentry =d_find_alias (inode); -if (dentry) { -spin_lock (&dentry->d_lock); - name = (const char *) dentry->d_name.name; - } -printk (KERN_DEBUG -"%s(%d): dirtied inode %lu (%s) on %s\n" , - current->comm,task_pid_nr (current), inode->i_ino, - name, inode->i_sb->s_id); -if (dentry) { -spin_unlock (&dentry->d_lock); -dput (dentry); - } - } -} -/** * __mark_inode_dirty - internal function * @inode: inode to mark
@@ -2168,9 +2146,6 @@ void __mark_inode_dirty(struct inode *inode, int flags) (dirtytime && (inode->i_state & I_DIRTY_INODE))) return; -if (unlikely (block_dump)) -block_dump___mark_inode_dirty (inode); -spin_lock (&inode->i_lock);if (dirtytime && (inode->i_state &I_DIRTY_INODE )) goto out_unlock_inode;
Signature · 1 line
2.30.2
Sasha Levin
maintainerPATCH 3/9 fs: dlm: cancel work sync othercon
In reply to Sasha LevinFrom: Alexander Aring <[email protected]>
[ Upstream commit c6aa00e3d20c2767ba3f57b64eb862572b9744b3 ]
These rx tx flags arguments are for signaling close_connection() from which worker they are called. Obviously the receive worker cannot cancel itself and vice versa for swork. For the othercon the receive worker should only be used, however to avoid deadlocks we should pass the same flags as the original close_connection() was called.
--- fs/dlm/lowcomms.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/dlm/lowcomms.c +1 -1
@@ -599,7 +599,7 @@ static void close_connection(struct connection *con, bool and_other, }if (con->othercon && and_other) {/* Will only re-enter once. */ -close_connection (con->othercon, false, true, true); +close_connection (con->othercon, false, tx, rx); }if (con->rx_page) {__free_page (con->rx_page);
Signature · 1 line
2.30.2
Sasha Levin
maintainerPATCH 4/9 random32: Fix implicit truncation warning in prandom_seed_state()
In reply to Sasha LevinFrom: Richard Fitzgerald <[email protected]>
[ Upstream commit d327ea15a305024ef0085252fa3657bbb1ce25f5 ]
sparse generates the following warning:
include/linux/prandom.h:114:45: sparse: sparse: cast truncates bits from constant value
This is because the 64-bit seed value is manipulated and then placed in a u32, causing an implicit cast and truncation. A forced cast to u32 doesn't prevent this warning, which is reasonable because a typecast doesn't prove that truncation was expected.
Logical-AND the value with 0xffffffff to make explicit that truncation to 32-bit is intended.
--- include/linux/prandom.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
include/linux/prandom.h +1 -1
@@ -93,7 +93,7 @@ static inline u32 __seed(u32 x, u32 m)*/ static inline void prandom_seed_state (struct rnd_state *state,u64 seed) { -u32 i = (seed >>32 ) ^ (seed <<10 ) ^ seed; +u32 i = ((seed >>32 ) ^ (seed <<10 ) ^ seed) &0xffffffffUL ; state->s1 =__seed (i,2U ); state->s2 =__seed (i,8U );
Signature · 1 line
2.30.2
Sasha Levin
maintainerPATCH 5/9 fs: dlm: fix memory leak when fenced
In reply to Sasha LevinFrom: Alexander Aring <[email protected]>
[ Upstream commit 700ab1c363c7b54c9ea3222379b33fc00ab02f7b ]
I got some kmemleak report when a node was fenced. The user space tool dlm_controld will therefore run some rmdir() in dlm configfs which was triggering some memleaks. This patch stores the sps and cms attributes which stores some handling for subdirectories of the configfs cluster entry and free them if they get released as the parent directory gets freed.
unreferenced object 0xffff88810d9e3e00 (size 192):
comm "dlm_controld", pid 342, jiffies 4294698126 (age 55438.801s) hex dump (first 32 bytes):
00 00 00 00 00 00 00 00 73 70 61 63 65 73 00 00 ........spaces..
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
backtrace:
[<00000000db8b640b>] make_cluster+0x5d/0x360
[<000000006a571db4>] configfs_mkdir+0x274/0x730
[<00000000b094501c>] vfs_mkdir+0x27e/0x340
[<0000000058b0adaf>] do_mkdirat+0xff/0x1b0
[<00000000d1ffd156>] do_syscall_64+0x40/0x80
[<00000000ab1408c8>] entry_SYSCALL_64_after_hwframe+0x44/0xae
unreferenced object 0xffff88810d9e3a00 (size 192):
comm "dlm_controld", pid 342, jiffies 4294698126 (age 55438.801s)
hex dump (first 32 bytes):
00 00 00 00 00 00 00 00 63 6f 6d 6d 73 00 00 00 ........comms...
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
backtrace:
[<00000000a7ef6ad2>] make_cluster+0x82/0x360
[<000000006a571db4>] configfs_mkdir+0x274/0x730
[<00000000b094501c>] vfs_mkdir+0x27e/0x340
[<0000000058b0adaf>] do_mkdirat+0xff/0x1b0
[<00000000d1ffd156>] do_syscall_64+0x40/0x80
[<00000000ab1408c8>] entry_SYSCALL_64_after_hwframe+0x44/0xae--- fs/dlm/config.c | 9 +++++++++ 1 file changed, 9 insertions(+)
fs/dlm/config.c +9 -0
@@ -80,6 +80,9 @@ struct dlm_cluster {unsigned int cl_new_rsb_count;unsigned int cl_recover_callbacks;char cl_cluster_name[DLM_LOCKSPACE_LEN ]; + +struct dlm_spaces *sps; +struct dlm_comms *cms; };static struct dlm_cluster *config_item_to_cluster (struct config_item *i)
@@ -356,6 +359,9 @@ static struct config_group *make_cluster(struct config_group *g,if (!cl || !sps || !cms) goto fail; + cl->sps = sps; + cl->cms = cms; +config_group_init_type_name (&cl->group, name, &cluster_type);config_group_init_type_name (&sps->ss_group,"spaces" , &spaces_type);config_group_init_type_name (&cms->cs_group,"comms" , &comms_type);
@@ -405,6 +411,9 @@ static void drop_cluster(struct config_group *g, struct config_item *i)static void release_cluster (struct config_item *i) {struct dlm_cluster *cl =config_item_to_cluster (i); + +kfree (cl->sps); +kfree (cl->cms);kfree (cl); }
Signature · 1 line
2.30.2
Sasha Levin
maintainerPATCH 6/9 ACPI: bus: Call kobject_put() in acpi_init() error path
In reply to Sasha LevinFrom: Hanjun Guo <[email protected]>
[ Upstream commit 4ac7a817f1992103d4e68e9837304f860b5e7300 ]
Although the system will not be in a good condition or it will not boot if acpi_bus_init() fails, it is still necessary to put the kobject in the error path before returning to avoid leaking memory.
--- drivers/acpi/bus.c | 1 + 1 file changed, 1 insertion(+)
drivers/acpi/bus.c +1 -0
@@ -1184,6 +1184,7 @@ static int __init acpi_init(void)init_acpi_device_notify (); result =acpi_bus_init ();if (result) { +kobject_put (acpi_kobj);disable_acpi ();return result; }
Signature · 1 line
2.30.2
Sasha Levin
maintainerPATCH 7/9 platform/x86: toshiba_acpi: Fix missing error code in toshiba_acpi_setup_keyboard()
In reply to Sasha LevinFrom: Jiapeng Chong <[email protected]>
[ Upstream commit 28e367127718a9cb85d615a71e152f7acee41bfc ]
The error code is missing in this code scenario, add the error code '-EINVAL' to the return value 'error'.
Eliminate the follow smatch warning:
drivers/platform/x86/toshiba_acpi.c:2834 toshiba_acpi_setup_keyboard()
warn: missing error code 'error'.
--- drivers/platform/x86/toshiba_acpi.c | 1 + 1 file changed, 1 insertion(+)
drivers/platform/x86/toshiba_acpi.c +1 -0
@@ -2866,6 +2866,7 @@ static int toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev)if (!dev->info_supported && !dev->system_event_supported) {pr_warn ("No hotkey query interface found\n" ); + error = -EINVAL ; goto err_remove_filter; }
Signature · 1 line
2.30.2
Sasha Levin
maintainerPATCH 8/9 ACPI: tables: Add custom DSDT file as makefile prerequisite
In reply to Sasha LevinFrom: Richard Fitzgerald <[email protected]>
[ Upstream commit d1059c1b1146870c52f3dac12cb7b6cbf39ed27f ]
A custom DSDT file is mostly used during development or debugging, and in that case it is quite likely to want to rebuild the kernel after changing ONLY the content of the DSDT.
This patch adds the custom DSDT as a prerequisite to tables.o to ensure a rebuild if the DSDT file is updated. Make will merge the prerequisites from multiple rules for the same target.
--- drivers/acpi/Makefile | 5 +++++ 1 file changed, 5 insertions(+)
drivers/acpi/Makefile +5 -0
@@ -7,6 +7,11 @@ ccflags-$(CONFIG_ACPI_DEBUG) += -DACPI_DEBUG_OUTPUT # # ACPI Boot-Time Table Parsing # +ifeq ($(CONFIG_ACPI_CUSTOM_DSDT),y) +tables.o: $(src)/../../include/$(subst $\",,$(CONFIG_ACPI_CUSTOM_DSDT_FILE)) ; + +endif + obj-$(CONFIG_ACPI) += tables.o obj-$(CONFIG_X86) += blacklist.o
Signature · 1 line
2.30.2
Sasha Levin
maintainerPATCH 9/9 ia64: mca_drv: fix incorrect array size calculation
In reply to Sasha LevinFrom: Arnd Bergmann <[email protected]>
[ Upstream commit c5f320ff8a79501bb59338278336ec43acb9d7e2 ]
gcc points out a mistake in the mca driver that goes back to before the git history:
arch/ia64/kernel/mca_drv.c: In function 'init_record_index_pools':arch/ia64/kernel/mca_drv.c:346:54: error: expression does not compute the number of elements in this array; element typ e is 'int', not 'size_t' {aka 'long unsigned int'} [-Werror=sizeof-array-div]
346 | for (i = 1; i < sizeof sal_log_sect_min_sizes/sizeof(size_t); i++)
| ^
This is the same as sizeof(size_t), which is two shorter than the actual array. Use the ARRAY_SIZE() macro to get the correct calculation instead.
--- arch/ia64/kernel/mca_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/ia64/kernel/mca_drv.c +1 -1
@@ -343,7 +343,7 @@ init_record_index_pools(void)/* - 2 - */ sect_min_size = sal_log_sect_min_sizes[0 ]; -for (i =1 ; i <sizeof sal_log_sect_min_sizes/sizeof (size_t ); i++) +for (i =1 ; i <ARRAY_SIZE (sal_log_sect_min_sizes); i++)if (sect_min_size > sal_log_sect_min_sizes[i]) sect_min_size = sal_log_sect_min_sizes[i];
Signature · 1 line
2.30.2