Сложная цель: история адского патча
Статья 2022 года, которую автор изначально написал на английском и забыл перевести. Исправляюсь.
В тот поганый февральский день, я все же решил одну из самых долгоживущих проблем с моим оборудованием под FreeBSD.
Которая была изящно описана в их багтрекере:
[psm] Курсор мыши замирает на несколько секунд в графическом окружении.
Как это часто бывает в жизни, за столь простым описанием скрывался лютейший п#здец, который выпил немало моей крови в попытках исправления:
баг никогда не повторялся на 100%, поведение отличалось между разными версиями FreeBSD и цикл «засыпания/пробуждения» мог полностью вывести тачпад из строя до перезагрузки.
Ушло пять (5) лет на то чтобы найти причину и решить эту проблему — помните об этом простом факте, когда вам будут рассказывать про «быструю разработку и искусственный интеллект».
Проблема возникала на моем ноутбуке Fujitsu-Siemens Lifebook U775, но должна была проявиться и на других моделях от других производителей — драйвер тачпада поменял поведение примерно после релиза FreeBSD 10.
Судя по собранному материалу, если на вашем ноутбуке с линуксом для решения проблемы с тачпадом необходим параметр ядра i8042.notimeout — в FreeBSD вас наверняка будет ожидать описанный баг.
Несколько примеров багрепортов для линукса на тему зависания тачпада и параметра i8042.notimeout:
https://askubuntu.com/questions/322906/touchpad-doesnt-work-on-fujitsu-lifebook-uh552
https://www.reddit.com/r/linux/comments/2a8cyf/anyway_to_fix_touchpad_without_using/
Корень зла
Вот этот блок в исходном коде драйвера psm.c и создавал все описанные выше проблемы:
Суть этого участка кода, в том чтобы отбрасывать полученные байты данных если они были получены с задержкой, превышающей заданный лимит.
Что вообщем-то логично для такого устройства как тачпад.
Но реалии работы железа как обычно вносят свои коррективы, смотрим реализацию этого же драйвера в ядре Linux, особенно вот этот замечательный комментарий:
When MUXERR condition is signalled the data register can only contain 0xfd, 0xfe or 0xff if implementation follows the spec. Unfortunately it is not always the case. Some KBCs also report 0xfc when there is nothing connected to the port while others sometimes get confused which port the data came from and signal error leaving the data intact. They do not revert to legacy mode (actually I’ve never seen KBC reverting to legacy mode yet, when we see one we’ll add proper handling). Anyway, we process 0xfc, 0xfd, 0xfe and 0xff as timeouts, and for the rest assume that the data came from the same serio last byte was transmitted (if transmission happened not too long ago).
Так что же в итоге происходит:
тачпад отправляет специальные данные, специфичные для этой модели и производителя, драйвер для FreeBSD их отбрасывает по таймауту.
Патч
Исправление заключается в удалении описанного блока, отвечающего за отбрасывание данных по таймауту.
Да это грязный хак и такое исправление никогда не примут в апстрим.
Зато после патча тачпад корректно переживает suspend/resume циклы и до сих пор не было ни одной паники ядра.
Что дает определенные надежды на стабильность.
--- psm.c 2022-02-17 21:22:45.481834000 +0300 +++ psm.c.1 2022-02-17 21:25:30.616384000 +0300 @@ -3011,14 +3011,14 @@ continue; getmicrouptime(&now); - if ((pb->inputbytes > 0) && + /*if ((pb->inputbytes > 0) && timevalcmp(&now, &sc->inputtimeout, >)) { VLOG(3, (LOG_DEBUG, "psmintr: delay too long; " "resetting byte count\n")); pb->inputbytes = 0; sc->syncerrors = 0; sc->pkterrors = 0; - } + }*/ sc->inputtimeout.tv_sec = PSM_INPUT_TIMEOUT / 1000000; sc->inputtimeout.tv_usec = PSM_INPUT_TIMEOUT % 1000000; timevaladd(&sc->inputtimeout, &now);
Сохраните как psm.patch и запустите:
cd /usr/src/sys/dev/atkbdc patch < /path/to/psm.patch
Обновление на 2025 год
Из-за выпуска новых релизов FreeBSD (статья писалась еще для 13й версии) — применение патча не сработает.
Вам будет необходимо вручную найти искомый блок и закомментировать его, после чего пересобрать ядро.