linux/drivers/usb
Yoshihiro Shimoda a349b95d7c usb: host: ohci: fix a race condition between shutdown and irq
This patch fixes an issue that the following error is
possible to happen when ohci hardware causes an interruption
and the system is shutting down at the same time.

[   34.851754] usb 2-1: USB disconnect, device number 2
[   35.166658] irq 156: nobody cared (try booting with the "irqpoll" option)
[   35.173445] CPU: 0 PID: 22 Comm: kworker/0:1 Not tainted 5.3.0-rc5 #85
[   35.179964] Hardware name: Renesas Salvator-X 2nd version board based on r8a77965 (DT)
[   35.187886] Workqueue: usb_hub_wq hub_event
[   35.192063] Call trace:
[   35.194509]  dump_backtrace+0x0/0x150
[   35.198165]  show_stack+0x14/0x20
[   35.201475]  dump_stack+0xa0/0xc4
[   35.204785]  __report_bad_irq+0x34/0xe8
[   35.208614]  note_interrupt+0x2cc/0x318
[   35.212446]  handle_irq_event_percpu+0x5c/0x88
[   35.216883]  handle_irq_event+0x48/0x78
[   35.220712]  handle_fasteoi_irq+0xb4/0x188
[   35.224802]  generic_handle_irq+0x24/0x38
[   35.228804]  __handle_domain_irq+0x5c/0xb0
[   35.232893]  gic_handle_irq+0x58/0xa8
[   35.236548]  el1_irq+0xb8/0x180
[   35.239681]  __do_softirq+0x94/0x23c
[   35.243253]  irq_exit+0xd0/0xd8
[   35.246387]  __handle_domain_irq+0x60/0xb0
[   35.250475]  gic_handle_irq+0x58/0xa8
[   35.254130]  el1_irq+0xb8/0x180
[   35.257268]  kernfs_find_ns+0x5c/0x120
[   35.261010]  kernfs_find_and_get_ns+0x3c/0x60
[   35.265361]  sysfs_unmerge_group+0x20/0x68
[   35.269454]  dpm_sysfs_remove+0x2c/0x68
[   35.273284]  device_del+0x80/0x370
[   35.276683]  hid_destroy_device+0x28/0x60
[   35.280686]  usbhid_disconnect+0x4c/0x80
[   35.284602]  usb_unbind_interface+0x6c/0x268
[   35.288867]  device_release_driver_internal+0xe4/0x1b0
[   35.293998]  device_release_driver+0x14/0x20
[   35.298261]  bus_remove_device+0x110/0x128
[   35.302350]  device_del+0x148/0x370
[   35.305832]  usb_disable_device+0x8c/0x1d0
[   35.309921]  usb_disconnect+0xc8/0x2d0
[   35.313663]  hub_event+0x6e0/0x1128
[   35.317146]  process_one_work+0x1e0/0x320
[   35.321148]  worker_thread+0x40/0x450
[   35.324805]  kthread+0x124/0x128
[   35.328027]  ret_from_fork+0x10/0x18
[   35.331594] handlers:
[   35.333862] [<0000000079300c1d>] usb_hcd_irq
[   35.338126] [<0000000079300c1d>] usb_hcd_irq
[   35.342389] Disabling IRQ #156

ohci_shutdown() disables all the interrupt and rh_state is set to
OHCI_RH_HALTED. In other hand, ohci_irq() is possible to enable
OHCI_INTR_SF and OHCI_INTR_MIE on ohci_irq(). Note that OHCI_INTR_SF
is possible to be set by start_ed_unlink() which is called:
 ohci_irq()
  -> process_done_list()
   -> takeback_td()
    -> start_ed_unlink()

So, ohci_irq() has the following condition, the issue happens by
&ohci->regs->intrenable = OHCI_INTR_MIE | OHCI_INTR_SF and
ohci->rh_state = OHCI_RH_HALTED:

	/* interrupt for some other device? */
	if (ints == 0 || unlikely(ohci->rh_state == OHCI_RH_HALTED))
		return IRQ_NOTMINE;

To fix the issue, ohci_shutdown() holds the spin lock while disabling
the interruption and changing the rh_state flag to prevent reenable
the OHCI_INTR_MIE unexpectedly. Note that io_watchdog_func() also
calls the ohci_shutdown() and it already held the spin lock, so that
the patch makes a new function as _ohci_shutdown().

This patch is inspired by a Renesas R-Car Gen3 BSP patch
from Tho Vu.

Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Cc: stable <stable@vger.kernel.org>
Acked-by: Alan Stern <stern@rowland.harvard.edu>
Link: https://lore.kernel.org/r/1566877910-6020-1-git-send-email-yoshihiro.shimoda.uh@renesas.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2019-08-28 22:48:37 +02:00
..
atm USB: atm: ueagle-atm.c: remove redundant license text 2019-06-03 15:21:57 +02:00
c67x00
chipidea usb: chipidea: udc: don't do hardware access if gadget has stopped 2019-08-21 09:45:49 -07:00
class usbtmc: more sanity checking for packet size 2019-08-21 09:45:46 -07:00
common USB: move usb debugfs directory creation to the usb common core 2019-06-06 08:59:19 +02:00
core usb: hcd: use managed device resources 2019-08-28 22:48:37 +02:00
dwc2 usb: add a hcd_uses_dma helper 2019-08-15 15:18:05 +02:00
dwc3 Revert "usb:gadget Separated decoding functions from dwc3 driver." 2019-07-04 13:02:09 +02:00
early drivers: Remove explicit invocations of mmiowb() 2019-04-08 12:01:02 +01:00
gadget usb: udc: lpc32xx: silence fall-through warning 2019-08-21 09:45:46 -07:00
host usb: host: ohci: fix a race condition between shutdown and irq 2019-08-28 22:48:37 +02:00
image scsi: usb: image: microtek: use sg helper to iterate over scatterlist 2019-06-20 15:21:32 -04:00
isp1760 usb: isp1760-hcd: Fix fall-through annotations 2019-05-01 18:13:52 +02:00
misc usb: iowarrior: fix deadlock on disconnect 2019-08-08 12:43:18 +02:00
mon docs: usb: rename files to .rst and add them to drivers-api 2019-06-20 14:28:36 +02:00
mtu3 Revert "usb: mtu3: fix up undefined reference to usb_debug_root" 2019-06-10 19:43:57 +02:00
musb usb: musb: dsps: Use dev_get_drvdata() 2019-04-30 17:55:08 +02:00
phy Driver Core and debugfs changes for 5.3-rc1 2019-07-12 12:24:03 -07:00
renesas_usbhs USB: more changes for v5.3 merge window 2019-07-03 13:48:54 +02:00
roles device connection: Find connections also by checking the references 2019-06-03 10:55:38 +02:00
serial USB: serial: option: add the BroadMobi BM818 card 2019-08-15 13:46:22 +02:00
storage usb-storage: Add new JMS567 revision to unusual_devs 2019-08-21 09:45:49 -07:00
typec typec: tcpm: fix a typo in the comparison of pdo_max_voltage 2019-08-28 22:48:37 +02:00
usbip usbip: Replace unused kvec array with single variable in vhci_send_cmd_unlink() 2019-06-05 11:54:38 +02:00
wusbcore wusb: switch to cbcmac transform 2019-06-18 08:52:34 +02:00
Kconfig dma-mapping updates for Linux 5.3 2019-07-12 15:13:55 -07:00
Makefile Revert "usb:cdns3 Add Cadence USB3 DRD Driver" 2019-07-04 13:01:33 +02:00
usb-skeleton.c usb: usb-skeleton: use irqsave() in USB's complete callback 2018-06-28 19:36:06 +09:00