irqchip fixes for 5.2

- CSky mpintc: allow interrupts to be broadcast
- TI sci-inta: fix error handling
- MIPS GIC: Fix local interrupt mapping
- ITS: Fix command queue wrapping
-----BEGIN PGP SIGNATURE-----

iQJJBAABCgAzFiEEn9UcU+C1Yxj9lZw9I9DQutE9ekMFAlz6T30VHG1hcmMuenlu
Z2llckBhcm0uY29tAAoJECPQ0LrRPXpD5EYP/15MdqgesZh9gMVtqN7xgqRaxmbw
AllhTqzOa0X3liBdLL0LAHhitNdQJSVIbcekcbfiz+9wx+YAjcKLsE1y9ujdC7Wu
vPl2nCIiRppJwSYejvgJjm8Li52RxCEp3xJ9+OBT4ZpkWvz/b+qL/Xl4JJnPtHcw
CDnfGujD6IhrOzGBtSCYyjwEryPFCWr5dXEYoh0+lHTIxJKL7AujI2KNthIVSNhc
2V/KJqeOy+BsfryegZeiiAS/XaAllc+/8rSuF2kMUtiVZzjFM3yZHMuZ1GZjXXlY
VgFU80yErPSBUOesFvkAH5d4Olql8m5Ni9J4dC3PitKU12N0SwvwcI2CzWgI3GNG
FDPA83zPap4qTjMq6oqd8aU7pJZ8Ek4aNvarbkKGm3Dhk7s+STmaOhqnO630g3lp
HxRRRiKejgIuZZ90/zJo/+3NhUT3fozTKogTfU3xieen+FOZk68pm1svG3hci6PW
PuwfGgp8pNfPPNv/FgbEIs36sCOCWwF8617l+kgC+Ji0DWukZ7BEWUQ3txKUXmZw
OgKp0tK1/ndEAXsHFBTAo4QqyFBsDmXccK5rUG4Et6a7K7dj4/OCNPkxF/cYD8c1
wmYwdpLJd6iTJN2H8c9xFv1Rui6iCN/IDNXC1yAeAkhpiAq7t1lVcXgywh5Vm8lf
Q8fRvpxIJyVUscg+
=MgSp
-----END PGP SIGNATURE-----
irqchip/gic-v3-its: Fix command queue pointer comparison bug

When we run several VMs with PCI passthrough and GICv4 enabled, not
pinning vCPUs, we will occasionally see below warnings in dmesg:

ITS queue timeout (65440 65504 480)
ITS cmd its_build_vmovp_cmd failed

The reason for the above issue is that in BUILD_SINGLE_CMD_FUNC:
1. Post the write command.
2. Release the lock.
3. Start to read GITS_CREADR to get the reader pointer.
4. Compare the reader pointer to the target pointer.
5. If reader pointer does not reach the target, sleep 1us and continue
to try.

If we have several processors running the above concurrently, other
CPUs will post write commands while the 1st CPU is waiting the
completion. So we may have below issue:

phase 1:
---rd_idx-----from_idx-----to_idx--0---------

wait 1us:

phase 2:
--------------from_idx-----to_idx--0-rd_idx--

That is the rd_idx may fly ahead of to_idx, and if in case to_idx is
near the wrap point, rd_idx will wrap around. So the below condition
will not be met even after 1s:

if (from_idx < to_idx && rd_idx >= to_idx)

There is another theoretical issue. For a slow and busy ITS, the
initial rd_idx may fall behind from_idx a lot, just as below:

---rd_idx---0--from_idx-----to_idx-----------

This will cause the wait function exit too early.

Actually, it does not make much sense to use from_idx to judge if
to_idx is wrapped, but we need a initial rd_idx when lock is still
acquired, and it can be used to judge whether to_idx is wrapped and
the current rd_idx is wrapped.

We switch to a method of calculating the delta of two adjacent reads
and accumulating it to get the sum, so that we can get the real rd_idx
from the wrapped value even when the queue is almost full.

Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Jason Cooper <jason@lakedaemon.net>
Signed-off-by: Heyi Guo <guoheyi@huawei.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
1 file changed