summaryrefslogtreecommitdiffstats
path: root/drivers/input/mouse/psmouse.h
diff options
context:
space:
mode:
authorTim Chen <tim.c.chen@linux.intel.com>2026-09-21 17:37:22 -0700
committerIngo Molnar <mingo@kernel.org>2026-09-22 10:49:53 +0200
commit0d6526f82c3cdefcca47f73f5fc08dc6f335eac6 (patch)
tree176dc2d685debcfb082c151ee94f2425ac96b364 /drivers/input/mouse/psmouse.h
downloadlinux-stable-0d6526f82c3cdefcca47f73f5fc08dc6f335eac6.tar.gz
linux-stable-0d6526f82c3cdefcca47f73f5fc08dc6f335eac6.zip
sched/cache: Keep nr_pref_llc_running in the runnable domain, to fix LLC mis-scheduling buggrafted
alb_break_llc() decides whether to break LLC preference during active load balance. It does so by testing that every runnable fair task on the source rq prefers its LLC: env->src_rq->nr_pref_llc_running == env->src_rq->cfs.h_nr_runnable But the two counters cover different sets. nr_pref_llc_running is updated in account_llc_enqueue()/account_llc_dequeue(), next to cfs_rq->nr_queued, so it follows queued tasks. h_nr_runnable is updated in set_delayed()/ clear_delayed() and drops delay-dequeued tasks. So under DELAY_DEQUEUE, a preferring task that goes to sleep stays counted in nr_pref_llc_running while h_nr_runnable falls. The equality then breaks, alb_break_llc() returns false, and active balance is free to pull a task off its preferred LLC. Active balance only moves runnable tasks, and this is the only LLC check it consults: once the stopper runs, LBF_ACTIVE_LB skips the per-task test in can_migrate_task(). The runnable set is the one we want. Fix it on the counter side. A task should be counted in nr_pref_llc_running exactly while it is both queued on its preferred LLC (pref_llc_queued) and runnable (!sched_delayed). Define that membership once in task_pref_llc_runnable(), and adjust the counter only through pref_llc_running_inc()/pref_llc_running_dec() from the four sites that change either input: account_llc_enqueue(), account_llc_dequeue(), set_delayed() and clear_delayed(). Gating every update on the same predicate keeps the delay, wake and dequeue paths from double-counting or underflowing; see the comments at those sites for the ordering. nr_llc_running and sd->llc_counts are not touched and stay on queued semantics. Fixes: 714059f79ff0 ("sched/cache: Handle moving single tasks to/from their preferred LLC") Closes: https://lore.kernel.org/lkml/20260827135000.735138-1-zhanxusheng@xiaomi.com/ Reported-by: Zhan Xusheng <zhanxusheng@xiaomi.com> Suggested-by: Chen Yu <yu.c.chen@intel.com> Signed-off-by: Tim Chen <tim.c.chen@linux.intel.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Signed-off-by: Ingo Molnar <mingo@kernel.org> Reviewed-by: Kayra Cizmeci <kayracizmeci@gmail.com> Cc: <stable@kernel.org> # v7.2.x Link: https://patch.msgid.link/06af61afedac32e6477f57feb4d658f6c411c3af.1790035273.git.tim.c.chen@linux.intel.com
Diffstat (limited to 'drivers/input/mouse/psmouse.h')
-rw-r--r--drivers/input/mouse/psmouse.h249
1 files changed, 249 insertions, 0 deletions
diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h
new file mode 100644
index 000000000..90ed8cd15
--- /dev/null
+++ b/drivers/input/mouse/psmouse.h
@@ -0,0 +1,249 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _PSMOUSE_H
+#define _PSMOUSE_H
+
+#define PSMOUSE_OOB_NONE 0x00
+#define PSMOUSE_OOB_EXTRA_BTNS 0x01
+
+#define PSMOUSE_CMD_SETSCALE11 0x00e6
+#define PSMOUSE_CMD_SETSCALE21 0x00e7
+#define PSMOUSE_CMD_SETRES 0x10e8
+#define PSMOUSE_CMD_GETINFO 0x03e9
+#define PSMOUSE_CMD_SETSTREAM 0x00ea
+#define PSMOUSE_CMD_SETPOLL 0x00f0
+#define PSMOUSE_CMD_POLL 0x00eb /* caller sets number of bytes to receive */
+#define PSMOUSE_CMD_RESET_WRAP 0x00ec
+#define PSMOUSE_CMD_GETID 0x02f2
+#define PSMOUSE_CMD_SETRATE 0x10f3
+#define PSMOUSE_CMD_ENABLE 0x00f4
+#define PSMOUSE_CMD_DISABLE 0x00f5
+#define PSMOUSE_CMD_RESET_DIS 0x00f6
+#define PSMOUSE_CMD_RESET_BAT 0x02ff
+
+#define PSMOUSE_RET_BAT 0xaa
+#define PSMOUSE_RET_ID 0x00
+#define PSMOUSE_RET_ACK 0xfa
+#define PSMOUSE_RET_NAK 0xfe
+
+enum psmouse_state {
+ PSMOUSE_IGNORE,
+ PSMOUSE_INITIALIZING,
+ PSMOUSE_RESYNCING,
+ PSMOUSE_CMD_MODE,
+ PSMOUSE_ACTIVATED,
+};
+
+/* psmouse protocol handler return codes */
+typedef enum {
+ PSMOUSE_BAD_DATA,
+ PSMOUSE_GOOD_DATA,
+ PSMOUSE_FULL_PACKET
+} psmouse_ret_t;
+
+enum psmouse_scale {
+ PSMOUSE_SCALE11,
+ PSMOUSE_SCALE21
+};
+
+enum psmouse_type {
+ PSMOUSE_NONE,
+ PSMOUSE_PS2,
+ PSMOUSE_PS2PP,
+ PSMOUSE_THINKPS,
+ PSMOUSE_GENPS,
+ PSMOUSE_IMPS,
+ PSMOUSE_IMEX,
+ PSMOUSE_SYNAPTICS,
+ PSMOUSE_ALPS,
+ PSMOUSE_LIFEBOOK,
+ PSMOUSE_TRACKPOINT,
+ PSMOUSE_TOUCHKIT_PS2,
+ PSMOUSE_CORTRON,
+ PSMOUSE_HGPK, /* No longer used */
+ PSMOUSE_ELANTECH,
+ PSMOUSE_FSP,
+ PSMOUSE_SYNAPTICS_RELATIVE,
+ PSMOUSE_CYPRESS,
+ PSMOUSE_FOCALTECH,
+ PSMOUSE_VMMOUSE,
+ PSMOUSE_BYD,
+ PSMOUSE_SYNAPTICS_SMBUS,
+ PSMOUSE_ELANTECH_SMBUS,
+ PSMOUSE_AUTO /* This one should always be last */
+};
+
+struct psmouse;
+
+struct psmouse_protocol {
+ enum psmouse_type type;
+ bool maxproto;
+ bool ignore_parity; /* Protocol should ignore parity errors from KBC */
+ bool try_passthru; /* Try protocol also on passthrough ports */
+ bool smbus_companion; /* "Protocol" is a stub, device is on SMBus */
+ const char *name;
+ const char *alias;
+ int (*detect)(struct psmouse *, bool);
+ int (*init)(struct psmouse *);
+};
+
+struct psmouse {
+ void *private;
+ struct input_dev *dev;
+ struct ps2dev ps2dev;
+ struct work_struct resync_work;
+ const char *vendor;
+ const char *name;
+ const struct psmouse_protocol *protocol;
+ unsigned char packet[8];
+ unsigned char badbyte;
+ unsigned char pktcnt;
+ unsigned char pktsize;
+ unsigned char oob_data_type;
+ unsigned char extra_buttons;
+ bool acks_disable_command;
+ unsigned int model;
+ unsigned long last;
+ unsigned long out_of_sync_cnt;
+ unsigned long num_resyncs;
+ enum psmouse_state state;
+ char devname[64];
+ char phys[32];
+
+ unsigned int rate;
+ unsigned int resolution;
+ unsigned int resetafter;
+ unsigned int resync_time;
+ bool smartscroll; /* Logitech only */
+
+ psmouse_ret_t (*protocol_handler)(struct psmouse *psmouse);
+ void (*set_rate)(struct psmouse *psmouse, unsigned int rate);
+ void (*set_resolution)(struct psmouse *psmouse, unsigned int resolution);
+ void (*set_scale)(struct psmouse *psmouse, enum psmouse_scale scale);
+
+ int (*reconnect)(struct psmouse *psmouse);
+ int (*fast_reconnect)(struct psmouse *psmouse);
+ void (*disconnect)(struct psmouse *psmouse);
+ void (*cleanup)(struct psmouse *psmouse);
+ int (*poll)(struct psmouse *psmouse);
+
+ void (*pt_activate)(struct psmouse *psmouse);
+ void (*pt_deactivate)(struct psmouse *psmouse);
+};
+
+struct psmouse *psmouse_from_serio(struct serio *serio);
+
+int psmouse_reset(struct psmouse *psmouse);
+void psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state);
+void psmouse_set_resolution(struct psmouse *psmouse, unsigned int resolution);
+psmouse_ret_t psmouse_process_byte(struct psmouse *psmouse);
+int psmouse_activate(struct psmouse *psmouse);
+int psmouse_deactivate(struct psmouse *psmouse);
+bool psmouse_matches_pnp_id(struct psmouse *psmouse, const char * const ids[]);
+
+void psmouse_report_standard_buttons(struct input_dev *, u8 buttons);
+void psmouse_report_standard_motion(struct input_dev *, u8 *packet);
+void psmouse_report_standard_packet(struct input_dev *, u8 *packet);
+
+struct psmouse_attribute {
+ struct device_attribute dattr;
+ void *data;
+ ssize_t (*show)(struct psmouse *psmouse, void *data, char *buf);
+ ssize_t (*set)(struct psmouse *psmouse, void *data,
+ const char *buf, size_t count);
+ bool protect;
+};
+#define to_psmouse_attr(a) container_of((a), struct psmouse_attribute, dattr)
+
+ssize_t psmouse_attr_show_helper(struct device *dev, struct device_attribute *attr,
+ char *buf);
+ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count);
+
+#define __PSMOUSE_DEFINE_ATTR_VAR(_name, _mode, _data, _show, _set, _protect) \
+static struct psmouse_attribute psmouse_attr_##_name = { \
+ .dattr = { \
+ .attr = { \
+ .name = __stringify(_name), \
+ .mode = _mode, \
+ }, \
+ .show = psmouse_attr_show_helper, \
+ .store = psmouse_attr_set_helper, \
+ }, \
+ .data = _data, \
+ .show = _show, \
+ .set = _set, \
+ .protect = _protect, \
+}
+
+#define __PSMOUSE_DEFINE_ATTR(_name, _mode, _data, _show, _set, _protect) \
+ static ssize_t _show(struct psmouse *, void *, char *); \
+ static ssize_t _set(struct psmouse *, void *, const char *, size_t); \
+ __PSMOUSE_DEFINE_ATTR_VAR(_name, _mode, _data, _show, _set, _protect)
+
+#define PSMOUSE_DEFINE_ATTR(_name, _mode, _data, _show, _set) \
+ __PSMOUSE_DEFINE_ATTR(_name, _mode, _data, _show, _set, true)
+
+#define PSMOUSE_DEFINE_RO_ATTR(_name, _mode, _data, _show) \
+ static ssize_t _show(struct psmouse *, void *, char *); \
+ __PSMOUSE_DEFINE_ATTR_VAR(_name, _mode, _data, _show, NULL, true)
+
+#define PSMOUSE_DEFINE_WO_ATTR(_name, _mode, _data, _set) \
+ static ssize_t _set(struct psmouse *, void *, const char *, size_t); \
+ __PSMOUSE_DEFINE_ATTR_VAR(_name, _mode, _data, NULL, _set, true)
+
+#ifndef psmouse_fmt
+#define psmouse_fmt(fmt) KBUILD_BASENAME ": " fmt
+#endif
+
+#define psmouse_dbg(psmouse, format, ...) \
+ dev_dbg(&(psmouse)->ps2dev.serio->dev, \
+ psmouse_fmt(format), ##__VA_ARGS__)
+#define psmouse_info(psmouse, format, ...) \
+ dev_info(&(psmouse)->ps2dev.serio->dev, \
+ psmouse_fmt(format), ##__VA_ARGS__)
+#define psmouse_warn(psmouse, format, ...) \
+ dev_warn(&(psmouse)->ps2dev.serio->dev, \
+ psmouse_fmt(format), ##__VA_ARGS__)
+#define psmouse_err(psmouse, format, ...) \
+ dev_err(&(psmouse)->ps2dev.serio->dev, \
+ psmouse_fmt(format), ##__VA_ARGS__)
+#define psmouse_notice(psmouse, format, ...) \
+ dev_notice(&(psmouse)->ps2dev.serio->dev, \
+ psmouse_fmt(format), ##__VA_ARGS__)
+#define psmouse_printk(level, psmouse, format, ...) \
+ dev_printk(level, \
+ &(psmouse)->ps2dev.serio->dev, \
+ psmouse_fmt(format), ##__VA_ARGS__)
+
+#ifdef CONFIG_MOUSE_PS2_SMBUS
+
+int psmouse_smbus_module_init(void);
+void psmouse_smbus_module_exit(void);
+
+struct i2c_board_info;
+
+int psmouse_smbus_init(struct psmouse *psmouse,
+ const struct i2c_board_info *board,
+ const void *pdata, size_t pdata_size,
+ bool need_deactivate,
+ bool leave_breadcrumbs);
+void psmouse_smbus_cleanup(struct psmouse *psmouse);
+
+#else /* !CONFIG_MOUSE_PS2_SMBUS */
+
+static inline int psmouse_smbus_module_init(void)
+{
+ return 0;
+}
+
+static inline void psmouse_smbus_module_exit(void)
+{
+}
+
+static inline void psmouse_smbus_cleanup(struct psmouse *psmouse)
+{
+}
+
+#endif /* CONFIG_MOUSE_PS2_SMBUS */
+
+#endif /* _PSMOUSE_H */