Because SCHED_FIFO is a broken scheduler model (see previous patches)
take away the priority field, the kernel can't possibly make an
informed decision.
No effective change.
Cc: broonie@kernel.org
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Ingo Molnar <mingo@kernel.org>
Reviewed-by: Douglas Anderson <dianders@chromium.org>
Reviewed-by: Guenter Roeck <groeck@chromium.org>
The use of `delay_usecs` in terminate_request() was replaced with the new
`delay` struct used by the SPI subsystem, however the unit was
set to SPI_DELAY_UNIT_NSECS instead of SPI_DELAY_UNIT_USECS. This fixes that.
Fixes: 7d3ca507fd ("platform/chrome: cros_ec_spi: Use new structure for SPI transfer delays")
Signed-off-by: Benson Leung <bleung@chromium.org>
In a recent change to the SPI subsystem [1], a new `delay` struct was added
to replace the `delay_usecs`. This change replaces the current
`delay_usecs` with `delay` for this driver.
The `spi_transfer_delay_exec()` function [in the SPI framework] makes sure
that both `delay_usecs` & `delay` are used (in this order to preserve
backwards compatibility).
[1] commit bebcfd272d ("spi: introduce `delay` field for
`spi_transfer` + spi_transfer_delay_exec()")
Signed-off-by: Sergiu Cuciurean <sergiu.cuciurean@analog.com>
Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
The 'cros_ec' core driver is the common interface for the cros_ec
transport drivers to do the shared operations to register, unregister,
suspend, resume and handle_event. The interface is provided by including
the header 'include/linux/platform_data/cros_ec_proto.h', however, instead
of have the implementation of these functions in cros_ec_proto.c, it is in
'cros_ec.c', which is a different kernel module. Apart from being a bad
practice, this can induce confusions allowing the users of the cros_ec
protocol to call these functions.
The register, unregister, suspend, resume and handle_event functions
*should* only be called by the different transport drivers (i2c, spi, lpc,
etc.), so make this a bit less confusing by moving these functions from
the public in-kernel space to a private include in platform/chrome, and
then, the interface for cros_ec module and for the cros_ec_proto module is
clean.
Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
Signed-off-by: Benson Leung <bleung@chromium.org>
There is a bit of mess between cros-ec mfd includes and platform
includes. For example, we have a linux/mfd/cros_ec.h include that
exports the interface implemented in platform/chrome/cros_ec_proto.c. Or
we have a linux/mfd/cros_ec_commands.h file that is non related to the
multifunction device (in the sense that is not exporting any function of
the mfd device). This causes crossed includes between mfd and
platform/chrome subsystems and makes the code difficult to read, apart
from creating 'curious' situations where a platform/chrome driver includes
a linux/mfd/cros_ec.h file just to get the exported functions that are
implemented in another platform/chrome driver.
In order to have a better separation on what the cros-ec multifunction
driver does and what the cros-ec core provides move and rework the
affected includes doing:
- Move cros_ec_commands.h to include/linux/platform_data/cros_ec_commands.h
- Get rid of the parts that are implemented in the platform/chrome/cros_ec_proto.c
driver from include/linux/mfd/cros_ec.h to a new file
include/linux/platform_data/cros_ec_proto.h
- Update all the drivers with the new includes, so
- Drivers that only need to know about the protocol include
- linux/platform_data/cros_ec_proto.h
- linux/platform_data/cros_ec_commands.h
- Drivers that need to know about the cros-ec mfd device also include
- linux/mfd/cros_ec.h
Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
Acked-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Acked-by: Mark Brown <broonie@kernel.org>
Acked-by: Wolfram Sang <wsa@the-dreams.de>
Acked-by: Neil Armstrong <narmstrong@baylibre.com>
Acked-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
Acked-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Acked-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Acked-by: Sebastian Reichel <sebastian.reichel@collabora.com>
Acked-by: Chanwoo Choi <cw00.choi@samsung.com>
Reviewed-by: Gwendal Grignou <gwendal@chromium.org>
Tested-by: Gwendal Grignou <gwendal@chromium.org>
Series changes: 3
- Fix dereferencing pointer to incomplete type 'struct cros_ec_dev' (lkp)
Signed-off-by: Lee Jones <lee.jones@linaro.org>
An MFD is a device that contains several sub-devices (cells). For instance,
the ChromeOS EC fits in this description as usually contains a charger and
can have other devices with different functions like a Real-Time Clock,
an Audio codec, a Real-Time Clock, ...
If you look at the driver, though, we're doing something odd. We have
two MFD cros-ec drivers where one of them (cros-ec-core) instantiates
another MFD driver as sub-driver (cros-ec-dev), and the latest
instantiates the different sub-devices (Real-Time Clock, Audio codec,
etc).
MFD
------------------------------------------
cros-ec-core
|___ mfd-cellA (cros-ec-dev)
| |__ mfd-cell0
| |__ mfd-cell1
| |__ ...
|
|___ mfd-cellB (cros-ec-dev)
|__ mfd-cell0
|__ mfd-cell1
|__ ...
The problem that was trying to solve is to describe some kind of topology for
the case where we have an EC (cros-ec) chained with another EC
(cros-pd). Apart from that this extends the bounds of what MFD was
designed to do we might be interested on have other kinds of topology that
can't be implemented in that way.
Let's prepare the code to move the cros-ec-core part from MFD to
platform/chrome as this is clearly a platform specific thing non-related
to a MFD device.
platform/chrome | MFD
------------------------------------------
|
cros-ec ________|___ cros-ec-dev
| |__ mfd-cell0
| |__ mfd-cell1
| |__ ...
|
cros-pd ________|___ cros-ec-dev
| |__ mfd-cell0
| |__ mfd-cell1
| |__ ...
Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
Acked-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Reviewed-by: Gwendal Grignou <gwendal@chromium.org>
Tested-by: Gwendal Grignou <gwendal@chromium.org>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
The SPI thingies request FIFO-99 by default, reduce this to FIFO-50.
FIFO-99 is the very highest priority available to SCHED_FIFO and
it not a suitable default; it would indicate the SPI work is the
most important work on the machine.
Cc: Benson Leung <bleung@chromium.org>
Cc: Enric Balletbo i Serra <enric.balletbo@collabora.com>
Cc: Guenter Roeck <groeck@chromium.org>
Cc: Mark Brown <broonie@kernel.org>
Cc: linux-spi@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Douglas Anderson <dianders@chromium.org>
Link: https://lore.kernel.org/r/20190801111541.917256884@infradead.org
Signed-off-by: Mark Brown <broonie@kernel.org>
All currently known ECs in the wild are very sensitive to timing.
Specifically the ECs are known to drop a transfer if more than 8 ms
passes from the assertion of the chip select until the transfer
finishes.
Let's use the new feature introduced in the patch (spi: Allow SPI
devices to request the pumping thread be realtime") to request the SPI
pumping thread be realtime. This means that if we get shunted off to
the SPI thread for whatever reason we won't get downgraded to low
priority.
NOTES:
- We still need to keep ourselves as high priority since the SPI core
doesn't guarantee that all transfers end up on the pumping thread
(in fact, it tries pretty hard to do them in the calling context).
- If future Chrome OS ECs ever fix themselves to be less sensitive
then we could consider adding a property (or compatible string) to
not set this property. For now we need it across the board.
Signed-off-by: Douglas Anderson <dianders@chromium.org>
Reviewed-by: Guenter Roeck <groeck@chromium.org>
Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
In commit 37a186225a ("platform/chrome: cros_ec_spi: Transfer
messages at high priority") we moved transfers to a high priority
workqueue. This helped make them much more reliable.
...but, we still saw failures.
We were actually finding ourselves competing for time with dm-crypt
which also scheduled work on HIGHPRI workqueues. While we can
consider reverting the change that made dm-crypt run its work at
HIGHPRI, the argument in commit a1b89132dc ("dm crypt: use
WQ_HIGHPRI for the IO and crypt workqueues") is somewhat compelling.
It does make sense for IO to be scheduled at a priority that's higher
than the default user priority. It also turns out that dm-crypt isn't
alone in using high priority like this. loop_prepare_queue() does
something similar for loopback devices.
Looking in more detail, it can be seen that the high priority
workqueue isn't actually that high of a priority. It runs at MIN_NICE
which is _fairly_ high priority but still below all real time
priority.
Should we move cros_ec_spi to real time priority to fix our problems,
or is this just escalating a priority war? I'll argue here that
cros_ec_spi _does_ belong at real time priority. Specifically
cros_ec_spi actually needs to run quickly for correctness. As I
understand this is exactly what real time priority is for.
There currently doesn't appear to be any way to use the standard
workqueue APIs with a real time priority, so we'll switch over to
using using a kthread worker. We'll match the priority that the SPI
core uses when it wants to do things on a realtime thread and just use
"MAX_RT_PRIO - 1".
This commit plus the patch ("platform/chrome: cros_ec_spi: Request the
SPI thread be realtime") are enough to get communications very close
to 100% reliable (the only known problem left is when serial console
is turned on, which isn't something that happens in shipping devices).
Specifically this test case now passes (tested on rk3288-veyron-jerry):
dd if=/dev/zero of=/var/log/foo.txt bs=4M count=512&
while true; do
ectool version > /dev/null;
done
It should be noted that "/var/log" is encrypted (and goes through
dm-crypt) and also passes through a loopback device.
Signed-off-by: Douglas Anderson <dianders@chromium.org>
Reviewed-by: Guenter Roeck <groeck@chromium.org>
Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
The Chrome OS EC driver attaches to devices using the of_match_table
even when ACPI is the underlying firmware. It does this using the
magic PRP0001 ACPI HID, which tells ACPI to go find an OF compatible
string under the hood and match on that.
The cros_ec_spi driver needs to provide the of_match_table regardless
of whether CONFIG_OF is enabled or not, since the table is used by
ACPI for PRP0001 devices.
Signed-off-by: Evan Green <evgreen@chromium.org>
Reviewed-by: Benson Leung <bleung@chromium.org>
Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
The software running on the Chrome OS Embedded Controller (cros_ec)
handles SPI transfers in a bit of a wonky way. Specifically if the EC
sees too long of a delay in a SPI transfer it will give up and the
transfer will be counted as failed. Unfortunately the timeout is
fairly short, though the actual number may be different for different
EC codebases.
We can end up tripping the timeout pretty easily if we happen to
preempt the task running the SPI transfer and don't get back to it for
a little while.
Historically this hasn't been a _huge_ deal because:
1. On old devices Chrome OS used to run PREEMPT_VOLUNTARY. That meant
we were pretty unlikely to take a big break from the transfer.
2. On recent devices we had faster / more processors.
3. Recent devices didn't use "cros-ec-spi-pre-delay". Using that
delay makes us more likely to trip this use case.
4. For whatever reasons (I didn't dig) old kernels seem to be less
likely to trip this.
5. For the most part it's kinda OK if a few transfers to the EC fail.
Mostly we're just polling the battery or doing some other task
where we'll try again.
Even with the above things, this issue has reared its ugly head
periodically. We could solve this in a nice way by adding reliable
retries to the EC protocol [1] or by re-designing the code in the EC
codebase to allow it to wait longer, but that code doesn't ever seem
to get changed. ...and even if it did, it wouldn't help old devices.
It's now time to finally take a crack at making this a little better.
This patch isn't guaranteed to make every cros_ec SPI transfer
perfect, but it should improve things by a few orders of magnitude.
Specifically you can try this on a rk3288-veyron Chromebook (which is
slower and also _does_ need "cros-ec-spi-pre-delay"):
md5sum /dev/zero &
md5sum /dev/zero &
md5sum /dev/zero &
md5sum /dev/zero &
while true; do
cat /sys/class/power_supply/sbs-20-000b/charge_now > /dev/null;
done
...before this patch you'll see boatloads of errors. After this patch I
don't see any in the testing I did.
The way this patch works is by effectively boosting the priority of
the cros_ec transfers. As far as I know there is no simple way to
just boost the priority of the current process temporarily so the way
we accomplish this is by queuing the work on the system_highpri_wq.
NOTE: this patch relies on the fact that the SPI framework attempts to
push the messages out on the calling context (which is the one that is
boosted to high priority). As I understand from earlier (long ago)
discussions with Mark Brown this should be a fine assumption. Even if
it isn't true sometimes this patch will still not make things worse.
[1] https://crbug.com/678675
Signed-off-by: Douglas Anderson <dianders@chromium.org>
Reviewed-by: Matthias Kaehlcke <mka@chromium.org>
Reviewed-by: Brian Norris <briannorris@chromium.org>
Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
Adopt the SPDX license identifier headers to ease license compliance
management. Also change the description for one more appropriate.
Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
Reviewed-by: Guenter Roeck <groeck@chromium.org>
Use devm_mfd_add_devices() for adding cros-ec core MFD child devices. This
reduces the need of remove callback from platform/chrome for removing the
MFD child devices.
Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
Reviewed-by: Guenter Roeck <groeck@chromium.org>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
There are some cros-ec transport drivers (I2C, SPI) living in MFD, while
others (LPC) living in drivers/platform. The transport drivers are more
platform specific. So, move the I2C and SPI transport drivers to the
platform/chrome directory. The patch also removes the MFD_ prefix of
their Kconfig symbols.
Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
Reviewed-by: Guenter Roeck <groeck@chromium.org>
Acked-by: Lee Jones <lee.jones@linaro.org>
Signed-off-by: Benson Leung <bleung@chromium.org>