xhci: harden xhci_find_next_ext_cap against device removal
xhci_find_next_ext_cap doesn't check for PCI hotplug removal and may use
the PCI master abort bit pattern (~0) to calculate a new PCI address
offset to read/write. The has lead to reproducable crashes when testing
surprise removal during device initialization on a Stratus platform, at
least after commit d5ddcdf4d6
("xhci: rework xhci extended capability
list parsing functions").
The crash is repeatable on a Stratus platform when injecting hardware
faults to induce xHCI host controller hotplug during driver
initialization. If a PCI read in xhci_find_next_ext_cap returns the
master abort pattern, quirk_usb_handoff_xhci may start using a bogus
ext_cap_offset to start searching more bogus PCI addresses.
Signed-off-by: Joe Lawrence <joe.lawrence@stratus.com>
Acked-by: Mathias Nyman <mathias.nyman@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Родитель
207b08b942
Коммит
89140fdaf1
|
@ -112,12 +112,16 @@ static inline int xhci_find_next_ext_cap(void __iomem *base, u32 start, int id)
|
||||||
offset = start;
|
offset = start;
|
||||||
if (!start || start == XHCI_HCC_PARAMS_OFFSET) {
|
if (!start || start == XHCI_HCC_PARAMS_OFFSET) {
|
||||||
val = readl(base + XHCI_HCC_PARAMS_OFFSET);
|
val = readl(base + XHCI_HCC_PARAMS_OFFSET);
|
||||||
|
if (val == ~0)
|
||||||
|
return 0;
|
||||||
offset = XHCI_HCC_EXT_CAPS(val) << 2;
|
offset = XHCI_HCC_EXT_CAPS(val) << 2;
|
||||||
if (!offset)
|
if (!offset)
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
do {
|
do {
|
||||||
val = readl(base + offset);
|
val = readl(base + offset);
|
||||||
|
if (val == ~0)
|
||||||
|
return 0;
|
||||||
if (XHCI_EXT_CAPS_ID(val) == id && offset != start)
|
if (XHCI_EXT_CAPS_ID(val) == id && offset != start)
|
||||||
return offset;
|
return offset;
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче