diff options
| author | Tim Chen <tim.c.chen@linux.intel.com> | 2026-09-21 17:37:22 -0700 |
|---|---|---|
| committer | Ingo Molnar <mingo@kernel.org> | 2026-09-22 10:49:53 +0200 |
| commit | 0d6526f82c3cdefcca47f73f5fc08dc6f335eac6 (patch) | |
| tree | 176dc2d685debcfb082c151ee94f2425ac96b364 /Documentation/input/ff.rst | |
| download | linux-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 'Documentation/input/ff.rst')
| -rw-r--r-- | Documentation/input/ff.rst | 265 |
1 files changed, 265 insertions, 0 deletions
diff --git a/Documentation/input/ff.rst b/Documentation/input/ff.rst new file mode 100644 index 000000000..5a1da42c3 --- /dev/null +++ b/Documentation/input/ff.rst @@ -0,0 +1,265 @@ +======================== +Force feedback for Linux +======================== + +:Author: Johann Deneux <johann.deneux@gmail.com> on 2001/04/22. +:Updated: Anssi Hannula <anssi.hannula@gmail.com> on 2006/04/09. + +You may redistribute this file. Please remember to include shape.svg and +interactive.svg as well. + +Introduction +~~~~~~~~~~~~ + +This document describes how to use force feedback devices under Linux. The +goal is not to support these devices as if they were simple input-only devices +(as it is already the case), but to really enable the rendering of force +effects. +This document only describes the force feedback part of the Linux input +interface. Please read joydev/joystick.rst and input.rst before reading further +this document. + +Instructions to the user +~~~~~~~~~~~~~~~~~~~~~~~~ + +To enable force feedback, you have to: + +1. have your kernel configured with evdev and a driver that supports your + device. +2. make sure evdev module is loaded and /dev/input/event* device files are + created. + +Before you start, let me WARN you that some devices shake violently during the +initialisation phase. This happens for example with my "AVB Top Shot Pegasus". +To stop this annoying behaviour, move your joystick to its limits. Anyway, you +should keep a hand on your device, in order to avoid it to break down if +something goes wrong. + +If you have a serial iforce device, you need to start inputattach. See +joydev/joystick.rst for details. + +Does it work ? +-------------- + +There is an utility called fftest that will allow you to test the driver:: + + % fftest /dev/input/eventXX + +Instructions to the developer +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +All interactions are done using the event API. That is, you can use ioctl() +and write() on /dev/input/eventXX. +This information is subject to change. + +Querying device capabilities +---------------------------- + +:: + + #include <linux/input.h> + #include <sys/ioctl.h> + + #define BITS_TO_LONGS(x) \ + (((x) + 8 * sizeof (unsigned long) - 1) / (8 * sizeof (unsigned long))) + unsigned long features[BITS_TO_LONGS(FF_CNT)]; + int ioctl(int file_descriptor, int request, unsigned long *features); + +"request" must be EVIOCGBIT(EV_FF, size of features array in bytes ) + +Returns the features supported by the device. features is a bitfield with the +following bits: + +- FF_CONSTANT can render constant force effects +- FF_PERIODIC can render periodic effects with the following waveforms: + + - FF_SQUARE square waveform + - FF_TRIANGLE triangle waveform + - FF_SINE sine waveform + - FF_SAW_UP sawtooth up waveform + - FF_SAW_DOWN sawtooth down waveform + - FF_CUSTOM custom waveform + +- FF_RAMP can render ramp effects +- FF_SPRING can simulate the presence of a spring +- FF_FRICTION can simulate friction +- FF_DAMPER can simulate damper effects +- FF_RUMBLE rumble effects +- FF_INERTIA can simulate inertia +- FF_GAIN gain is adjustable +- FF_AUTOCENTER autocenter is adjustable + +.. note:: + + - In most cases you should use FF_PERIODIC instead of FF_RUMBLE. All + devices that support FF_RUMBLE support FF_PERIODIC (square, triangle, + sine) and the other way around. + + - The exact syntax FF_CUSTOM is undefined for the time being as no driver + supports it yet. + +:: + + int ioctl(int fd, EVIOCGEFFECTS, int *n); + +Returns the number of effects the device can keep in its memory. + +Uploading effects to the device +------------------------------- + +:: + + #include <linux/input.h> + #include <sys/ioctl.h> + + int ioctl(int file_descriptor, int request, struct ff_effect *effect); + +"request" must be EVIOCSFF. + +"effect" points to a structure describing the effect to upload. The effect is +uploaded, but not played. +The content of effect may be modified. In particular, its field "id" is set +to the unique id assigned by the driver. This data is required for performing +some operations (removing an effect, controlling the playback). +The "id" field must be set to -1 by the user in order to tell the driver to +allocate a new effect. + +Effects are file descriptor specific. + +See <uapi/linux/input.h> for a description of the ff_effect struct. You +should also find help in a few sketches, contained in files shape.svg +and interactive.svg: + +.. kernel-figure:: shape.svg + + Shape + +.. kernel-figure:: interactive.svg + + Interactive + + +Removing an effect from the device +---------------------------------- + +:: + + int ioctl(int fd, EVIOCRMFF, effect.id); + +This makes room for new effects in the device's memory. Note that this also +stops the effect if it was playing. + +Controlling the playback of effects +----------------------------------- + +Control of playing is done with write(). Below is an example: + +:: + + #include <linux/input.h> + #include <unistd.h> + + struct input_event play; + struct input_event stop; + struct ff_effect effect; + int fd; + ... + fd = open("/dev/input/eventXX", O_RDWR); + ... + /* Play three times */ + play.type = EV_FF; + play.code = effect.id; + play.value = 3; + + write(fd, (const void*) &play, sizeof(play)); + ... + /* Stop an effect */ + stop.type = EV_FF; + stop.code = effect.id; + stop.value = 0; + + write(fd, (const void*) &stop, sizeof(stop)); + +Setting the gain +---------------- + +Not all devices have the same strength. Therefore, users should set a gain +factor depending on how strong they want effects to be. This setting is +persistent across access to the driver. + +:: + + /* Set the gain of the device + int gain; /* between 0 and 100 */ + struct input_event ie; /* structure used to communicate with the driver */ + + ie.type = EV_FF; + ie.code = FF_GAIN; + ie.value = 0xFFFFUL * gain / 100; + + if (write(fd, &ie, sizeof(ie)) == -1) + perror("set gain"); + +Enabling/Disabling autocenter +----------------------------- + +The autocenter feature quite disturbs the rendering of effects in my opinion, +and I think it should be an effect, which computation depends on the game +type. But you can enable it if you want. + +:: + + int autocenter; /* between 0 and 100 */ + struct input_event ie; + + ie.type = EV_FF; + ie.code = FF_AUTOCENTER; + ie.value = 0xFFFFUL * autocenter / 100; + + if (write(fd, &ie, sizeof(ie)) == -1) + perror("set auto-center"); + +A value of 0 means "no auto-center". + +Dynamic update of an effect +--------------------------- + +Proceed as if you wanted to upload a new effect, except that instead of +setting the id field to -1, you set it to the wanted effect id. +Normally, the effect is not stopped and restarted. However, depending on the +type of device, not all parameters can be dynamically updated. For example, +the direction of an effect cannot be updated with iforce devices. In this +case, the driver stops the effect, up-load it, and restart it. + +Therefore it is recommended to dynamically change direction while the effect +is playing only when it is ok to restart the effect with a replay count of 1. + +Information about the status of effects +--------------------------------------- + +Every time the status of an effect is changed, an event is sent. The values +and meanings of the fields of the event are as follows:: + + struct input_event { + /* When the status of the effect changed */ + struct timeval time; + + /* Set to EV_FF_STATUS */ + unsigned short type; + + /* Contains the id of the effect */ + unsigned short code; + + /* Indicates the status */ + unsigned int value; + }; + + FF_STATUS_STOPPED The effect stopped playing + FF_STATUS_PLAYING The effect started to play + +.. note:: + + - Status feedback is only supported by iforce driver. If you have + a really good reason to use this, please contact + linux-joystick@atrey.karlin.mff.cuni.cz or anssi.hannula@gmail.com + so that support for it can be added to the rest of the drivers. |
