Message ID | 20180503051326.10477-2-kai.heng.feng@canonical.com |
---|---|
State | New |
Headers | show |
Series | Fix TBT ICM firmware issue | expand |
On 05/03/18 07:13, Kai-Heng Feng wrote: > From: Mika Westerberg <mika.westerberg@linux.intel.com> > > BugLink: https://bugs.launchpad.net/bugs/1768292 > > On Lenovo ThinkPad Yoga 370 (and possibly some other Lenovo models as > well) the Thunderbolt host controller sometimes comes up in such way > that the ICM firmware is not running properly. This is most likely an > issue in BIOS/firmware but as side-effect driver crashes the kernel due > to NULL pointer dereference: > > BUG: unable to handle kernel NULL pointer dereference at 0000000000000980 > IP: pci_write_config_dword+0x5/0x20 > Call Trace: > pcie2cio_write+0x3b/0x70 [thunderbolt] > icm_driver_ready+0x168/0x260 [thunderbolt] > ? tb_ctl_start+0x50/0x70 [thunderbolt] > tb_domain_add+0x73/0xf0 [thunderbolt] > nhi_probe+0x182/0x300 [thunderbolt] > local_pci_probe+0x42/0xa0 > ? pci_match_device+0xd9/0x100 > pci_device_probe+0x146/0x1b0 > driver_probe_device+0x315/0x480 > ... > > Instead of crashing update the driver to bail out gracefully if we > encounter such situation. > > Fixes: f67cf491175a ("thunderbolt: Add support for Internal Connection Manager (ICM)") > Reported-by: Jordan Glover <Golden_Miller83@protonmail.ch> > Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com> > Acked-by: Yehezkel Bernat <yehezkel.bernat@intel.com> > Cc: stable@vger.kernel.org > (cherry picked from commit ea9d7bb798900096f26c585957d6ad9c532417e6) > Signed-off-by: Kai-Heng Feng <kai.heng.feng@canonical.com> Acked-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com> > --- > drivers/thunderbolt/icm.c | 3 +++ > 1 file changed, 3 insertions(+) > > diff --git a/drivers/thunderbolt/icm.c b/drivers/thunderbolt/icm.c > index 6b1041677604..2d2ceda9aa26 100644 > --- a/drivers/thunderbolt/icm.c > +++ b/drivers/thunderbolt/icm.c > @@ -1452,6 +1452,9 @@ static int icm_firmware_reset(struct tb *tb, struct tb_nhi *nhi) > struct icm *icm = tb_priv(tb); > u32 val; > > + if (!icm->upstream_port) > + return -ENODEV; > + > /* Put ARC to wait for CIO reset event to happen */ > val = ioread32(nhi->iobase + REG_FW_STS); > val |= REG_FW_STS_CIO_RESET_REQ; >
diff --git a/drivers/thunderbolt/icm.c b/drivers/thunderbolt/icm.c index 6b1041677604..2d2ceda9aa26 100644 --- a/drivers/thunderbolt/icm.c +++ b/drivers/thunderbolt/icm.c @@ -1452,6 +1452,9 @@ static int icm_firmware_reset(struct tb *tb, struct tb_nhi *nhi) struct icm *icm = tb_priv(tb); u32 val; + if (!icm->upstream_port) + return -ENODEV; + /* Put ARC to wait for CIO reset event to happen */ val = ioread32(nhi->iobase + REG_FW_STS); val |= REG_FW_STS_CIO_RESET_REQ;