kernel panic - panic: ehci_device_clear_toggle: queue active

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

kernel panic - panic: ehci_device_clear_toggle: queue active

Björn Ketelaars
Hello,

I repeatedly hit the kernel panic below. Easy to reproduce as it happens over
and over again within 60 minutes after rebooting. Root cause is not known.

I'm running snapshot on an USB stick. I tried different USB ports with the same
result. Next step will be an attempt with a different USB stick.

I think this issue has been mentioned before:

https://marc.info/?t=141840591400001&r=1&w=3
http://openbsd-archive.7691.n7.nabble.com/panic-ehci-device-clear-toggle-queue-active-td231729.html
http://article.gmane.org/gmane.os.openbsd.bugs/19812/

Any ideas on how to tackle this issue?

--
Björn Ketelaars
GPG key: 0x4F0E5F21



OpenBSD 5.8-current (GENERIC.MP) #0: Mon Nov 30 08:22:20 CET 2015
    [hidden email]:/storage/8899fc1454db04de.a/home/code/src/sys/arch/amd64/compile/GENERIC.MP
real mem = 4242419712 (4045MB)
avail mem = 4109725696 (3919MB)
mpath0 at root
scsibus0 at mpath0: 256 targets
mainbus0 at root
bios0 at mainbus0: SMBIOS rev. 2.7 @ 0xf3bdb000 (64 entries)
bios0: vendor HP version "J06" date 11/09/2013
bios0: HP ProLiant MicroServer Gen8
acpi0 at bios0: rev 2
acpi0: sleep states S0 S4 S5
acpi0: tables DSDT FACP SPCR MCFG HPET FFFF SPMI ERST APIC FFFF BERT HEST FFFF FFFF SSDT SSDT SSDT SSDT SSDT
acpi0: wakeup devices PCI0(S4)
acpitimer0 at acpi0: 3579545 Hz, 24 bits
acpimcfg0 at acpi0 addr 0xf4000000, bus 0-63
acpihpet0 at acpi0: 14318179 Hz
acpimadt0 at acpi0 addr 0xfee00000: PC-AT compat
cpu0 at mainbus0: apid 0 (boot processor)
cpu0: Intel(R) Celeron(R) CPU G1610T @ 2.30GHz, 2295.13 MHz
cpu0: FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE,SSE3,PCLMUL,DTES64,MWAIT,DS-CPL,VMX,EST,TM2,SSSE3,CX16,xTPR,PDCM,PCID,SSE4.1,SSE4.2,POPCNT,DEADLINE,XSAVE,NXE,LONG,LAHF,PERF,ITSC,FSGSBASE,SMEP,ERMS,SENSOR,ARAT
cpu0: 256KB 64b/line 8-way L2 cache
cpu0: smt 0, core 0, package 0
mtrr: Pentium Pro MTRR support, 10 var ranges, 88 fixed ranges
cpu0: apic clock running at 99MHz
cpu0: mwait min=64, max=64, C-substates=0.2.1.1, IBE
cpu1 at mainbus0: apid 2 (application processor)
cpu1: Intel(R) Celeron(R) CPU G1610T @ 2.30GHz, 2294.79 MHz
cpu1: FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE,SSE3,PCLMUL,DTES64,MWAIT,DS-CPL,VMX,EST,TM2,SSSE3,CX16,xTPR,PDCM,PCID,SSE4.1,SSE4.2,POPCNT,DEADLINE,XSAVE,NXE,LONG,LAHF,PERF,ITSC,FSGSBASE,SMEP,ERMS,SENSOR,ARAT
cpu1: 256KB 64b/line 8-way L2 cache
cpu1: smt 0, core 1, package 0
ioapic0 at mainbus0: apid 8 pa 0xfec00000, version 20, 24 pins
ioapic0: misconfigured as apic 0, remapped to apid 8
acpiprt0 at acpi0: bus 13 (IPT1)
acpiprt1 at acpi0: bus -1 (IPT2)
acpiprt2 at acpi0: bus -1 (IPT3)
acpiprt3 at acpi0: bus -1 (IPT4)
acpiprt4 at acpi0: bus 3 (IPT5)
acpiprt5 at acpi0: bus -1 (IPT6)
acpiprt6 at acpi0: bus 4 (IPT7)
acpiprt7 at acpi0: bus 1 (IPT8)
acpiprt8 at acpi0: bus 7 (PT02)
acpiprt9 at acpi0: bus -1 (PT03)
acpiprt10 at acpi0: bus 2 (PT05)
acpiprt11 at acpi0: bus 0 (PCI0)
acpicpu0 at acpi0: C2(350@96 mwait.1@0x20), C1(1000@1 mwait.1)
acpicpu1 at acpi0: C2(350@96 mwait.1@0x20), C1(1000@1 mwait.1)
acpitz0 at acpi0: critical temperature is 31 degC
ipmi at mainbus0 not configured
pci0 at mainbus0 bus 0
pchb0 at pci0 dev 0 function 0 "Intel Core 3G Host" rev 0x09
ppb0 at pci0 dev 1 function 0 "Intel Core 3G PCIE" rev 0x09: msi
pci1 at ppb0 bus 7
ppb1 at pci0 dev 6 function 0 "Intel Core 3G PCIE" rev 0x09: msi
pci2 at ppb1 bus 2
ehci0 at pci0 dev 26 function 0 "Intel 6 Series USB" rev 0x05: apic 8 int 21
usb0 at ehci0: USB revision 2.0
uhub0 at usb0 "Intel EHCI root hub" rev 2.00/1.00 addr 1
ppb2 at pci0 dev 28 function 0 "Intel 6 Series PCIE" rev 0xb5
pci3 at ppb2 bus 13
ppb3 at pci0 dev 28 function 4 "Intel 6 Series PCIE" rev 0xb5
pci4 at ppb3 bus 3
bge0 at pci4 dev 0 function 0 "Broadcom BCM5720" rev 0x00, BCM5720 A0 (0x5720000), APE firmware NCSI 1.2.46.0: msi, address d0:bf:9c:46:de:14
brgphy0 at bge0 phy 1: BCM5720C 10/100/1000baseT PHY, rev. 0
bge1 at pci4 dev 0 function 1 "Broadcom BCM5720" rev 0x00, BCM5720 A0 (0x5720000), APE firmware NCSI 1.2.46.0: msi, address d0:bf:9c:46:de:15
brgphy1 at bge1 phy 2: BCM5720C 10/100/1000baseT PHY, rev. 0
ppb4 at pci0 dev 28 function 6 "Intel 6 Series PCIE" rev 0xb5
pci5 at ppb4 bus 4
xhci0 at pci5 dev 0 function 0 "Renesas uPD720201 xHCI" rev 0x03: msi
usb1 at xhci0: USB revision 3.0
uhub1 at usb1 "Renesas xHCI root hub" rev 3.00/1.00 addr 1
ppb5 at pci0 dev 28 function 7 "Intel 6 Series PCIE" rev 0xb5
pci6 at ppb5 bus 1
"Hewlett-Packard iLO3 Slave" rev 0x05 at pci6 dev 0 function 0 not configured
vga1 at pci6 dev 0 function 1 "Matrox MGA G200eH" rev 0x00
wsdisplay0 at vga1 mux 1: console (80x25, vt100 emulation)
wsdisplay0: screen 1-5 added (80x25, vt100 emulation)
"Hewlett-Packard iLO3 Management" rev 0x05 at pci6 dev 0 function 2 not configured
uhci0 at pci6 dev 0 function 4 "Hewlett-Packard USB" rev 0x02: apic 8 int 16
usb2 at uhci0: USB revision 1.0
uhub2 at usb2 "Hewlett-Packard UHCI root hub" rev 1.00/1.00 addr 1
ehci1 at pci0 dev 29 function 0 "Intel 6 Series USB" rev 0x05: apic 8 int 20
usb3 at ehci1: USB revision 2.0
uhub3 at usb3 "Intel EHCI root hub" rev 2.00/1.00 addr 1
ppb6 at pci0 dev 30 function 0 "Intel 82801BA Hub-to-PCI" rev 0xa5
pci7 at ppb6 bus 20
pcib0 at pci0 dev 31 function 0 "Intel C204 LPC" rev 0x05
ahci0 at pci0 dev 31 function 2 "Intel 6 Series AHCI" rev 0x05: msi, AHCI 1.3
ahci0: port 0: 6.0Gb/s
ahci0: port 1: 6.0Gb/s
ahci0: port 2: 3.0Gb/s
ahci0: port 3: 3.0Gb/s
scsibus1 at ahci0: 32 targets
sd0 at scsibus1 targ 0 lun 0: <ATA, Hitachi HDS5C303, MZ6O> SCSI3 0/direct fixed naa.5000cca37ec4cabf
sd0: 2861588MB, 512 bytes/sector, 5860533168 sectors
sd1 at scsibus1 targ 1 lun 0: <ATA, WDC WD30EFRX-68E, 80.0> SCSI3 0/direct fixed naa.50014ee6ae93cca7
sd1: 2861588MB, 512 bytes/sector, 5860533168 sectors
sd2 at scsibus1 targ 2 lun 0: <ATA, SAMSUNG HD204UI, 1AQ1> SCSI3 0/direct fixed naa.50024e9204c857d8
sd2: 1907729MB, 512 bytes/sector, 3907029168 sectors
sd3 at scsibus1 targ 3 lun 0: <ATA, SAMSUNG HD204UI, 1AQ1> SCSI3 0/direct fixed naa.50024e900430ce1c
sd3: 1907729MB, 512 bytes/sector, 3907029168 sectors
isa0 at pcib0
isadma0 at isa0
com0 at isa0 port 0x3f8/8 irq 4: ns16550a, 16 byte fifo
com0: console
pckbc0 at isa0 port 0x60/5 irq 1 irq 12
pckbd0 at pckbc0 (kbd slot)
wskbd0 at pckbd0: console keyboard, using wsdisplay0
pcppi0 at isa0 port 0x61
spkr0 at pcppi0
uhub4 at uhub0 port 1 "Intel Rate Matching Hub" rev 2.00/0.00 addr 2
umass0 at uhub4 port 6 configuration 1 interface 0 " USB DISK 2.0" rev 2.00/1.00 addr 3
umass0: using SCSI over Bulk-Only
scsibus2 at umass0: 2 targets, initiator 0
sd4 at scsibus2 targ 1 lun 0: <, USB DISK 2.0, PMAP> SCSI2 0/direct removable serial.13fe3e0002020C6B02FC
sd4: 15272MB, 512 bytes/sector, 31277056 sectors
uhub5 at uhub3 port 1 "Intel Rate Matching Hub" rev 2.00/0.00 addr 2
uhub6 at uhub5 port 3 "Standard Microsystems product 0x2660" rev 2.00/8.01 addr 3
umass1 at uhub6 port 1 configuration 1 interface 0 "Generic Ultra Fast Media Reader" rev 2.00/2.09 addr 4
umass1: using SCSI over Bulk-Only
scsibus3 at umass1: 2 targets, initiator 0
sd5 at scsibus3 targ 1 lun 0: <HP iLO, Internal SD-CARD, 2.09> SCSI0 0/direct fixed serial.04244030000002660A01
sd5: 7580MB, 512 bytes/sector, 15523840 sectors
vscsi0 at root
scsibus4 at vscsi0: 256 targets
softraid0 at root
scsibus5 at softraid0: 256 targets
root on sd4a (00bfb5c3f8a76186.a) swap on sd4b dump on sd4b

ddb{0}> show panic
ehci_device_clear_toggle: queue active
ddb{0}>

ddb{0}> trace
Debugger() at Debugger+0x9
panic() at panic+0xfe
ehci_device_clear_toggle() at ehci_device_clear_toggle+0x2b
umass_clear_endpoint_stall() at umass_clear_endpoint_stall+0x44
usb_transfer_complete() at usb_transfer_complete+0x26c
ehci_softintr() at ehci_softintr+0x43
softintr_dispatch() at softintr_dispatch+0x8b
Xsoftnet() at Xsoftnet+0x1f
--- interrupt ---
end of kernel
end trace frame: 0x20, count: -8
0x8:
ddb{0}>

ddb{0}> ps
   TID   PPID   PGRP    UID  S       FLAGS  WAIT          COMMAND
 25526    483  25598      0  3    0x100082  piperd        grep
 25050    483  25598      0  3    0x100082  piperd        sed
 27557    483  25598      0  3         0x2  syncxs        atactl
   483  25598  25598      0  3    0x10008a  pause         sh
 25598   2398  25598      0  3    0x10008a  pause         sh
  2398  30580  30580      0  3    0x100090  piperd        cron
 10975      1  10975      0  3    0x100083  ttyin         getty
 25638      1  25638      0  3    0x100083  ttyin         getty
  8972      1   8972      0  3    0x100083  ttyin         getty
 31258      1  31258      0  3    0x100083  ttyin         getty
  9580      1   9580      0  3    0x100083  ttyin         getty
 16198      1  16198      0  3    0x100083  ttyin         getty
 30580      1  30580      0  3    0x100098  poll          cron
  5866      1   5866    662  3        0x80  kqread        transmission-dae
 16379      1   5866    662  3   0x4000080  kqread        transmission-dae
 26540      1  26540      0  3        0x80  poll          nmbd
 13642      1  13642      0  3        0x90  poll          smbd
  6836      1   6836    749  3        0x90  nanosleep     nzbget
 24620      1   6836    749  3   0x4000090  netcon        nzbget
 30906      1   6836    749  3   0x4000090  nanosleep     nzbget
  3932      1   6836    749  3   0x4000090  nanosleep     nzbget
 11444      1   6836    749  3   0x4000090  nanosleep     nzbget
 26450      1   6836    749  3   0x4000090  nanosleep     nzbget
 23903      1   6836    749  3   0x4000090  nanosleep     nzbget
 20793  27335  27335     95  3    0x100090  kqread        smtpd
 29125  27335  27335     95  3    0x100090  kqread        smtpd
  5108  27335  27335     95  3    0x100090  kqread        smtpd
 14412  27335  27335     95  3    0x100090  kqread        smtpd
   989  27335  27335     95  3    0x100090  kqread        smtpd
 32618  27335  27335    103  3    0x100090  kqread        smtpd
 27335      1  27335      0  3    0x100080  kqread        smtpd
 18058  28997  28997     89  3        0x90  kqread        relayd
  5617  28997  28997     89  3        0x90  kqread        relayd
  5554  18329  18329     89  3    0x100090  kqread        relayd
 25504  18329  18329     89  3    0x100090  kqread        relayd
 18329  29635  18329     89  3    0x100090  kqread        relayd
 28997  29635  28997     89  3        0x90  kqread        relayd
 32011  29635  32011     89  3    0x100090  kqread        relayd
 24438  29635  24438     89  3    0x100090  kqread        relayd
 29635      1  29635      0  3        0x80  kqread        relayd
 27786      1  27786      0  3        0x80  select        sshd
  1789      1   1789      0  3    0x100080  poll          ntpd
 23729  13603  23729     83  3    0x100090  poll          ntpd
 13603      1  13603     83  3    0x100090  poll          ntpd
 10327   9671   9671     74  3    0x100090  bpf           pflogd
  9671      1   9671      0  3        0x80  netio         pflogd
  7727   5367   5367     73  3    0x100090  kqread        syslogd
  5367      1   5367      0  3    0x100080  netio         syslogd
 10482      1  10482     77  3        0x90  poll          dhclient
 21402      1  21402      0  3        0x80  poll          dhclient
 28213      0      0      0  3     0x14200  pgzero        zerothread
 15372      0      0      0  3     0x14200  aiodoned      aiodoned
 17964      0      0      0  3     0x14200  syncer        update
  7028      0      0      0  3     0x14200  cleaner       cleaner
 14247      0      0      0  3     0x14200  reaper        reaper
  8876      0      0      0  3     0x14200  pgdaemon      pagedaemon
 13349      0      0      0  3     0x14200  bored         crypto
 30917      0      0      0  3     0x14200  pftm          pfpurge
 16588      0      0      0  3     0x14200  usbtsk        usbtask
   593      0      0      0  3     0x14200  usbatsk       usbatsk
 29283      0      0      0  3  0x40014200  acpi0         acpi0
 31691      0      0      0  3     0x14200  bored         sbar
  6917      0      0      0  7  0x40014200                idle1
  3727      0      0      0  3     0x14200  bored         sensors
 22383      0      0      0  3     0x14200  bored         softnet
 28393      0      0      0  3     0x14200  bored         systqmp
 11456      0      0      0  3     0x14200  bored         systq
 18772      0      0      0  3     0x14200  bored         sbar
*28300      0      0      0  7  0x40014200                idle0
     1      0      1      0  3        0x82  wait          init
     0     -1      0      0  3     0x10200  scheduler     swapper
ddb{0}>

ddb{0}> show registers
rdi                              0x1
rsi                            0x292
rbp               0xffff800022158b70
rbx               0xffffffff816fb928    bwi_led_duration+0x3088
rdx                                0
rcx               0xffffffff818b52a0    cpu_info_primary
rax                              0x1
r8                0xffff800022158a90
r9                0xffffffff816fb928    bwi_led_duration+0x3088
r10               0xffff800022158b00
r11               0xffffffff810866a0    comcnputc
r12                            0x100
r13               0xffff800022158b80
r14               0xffffffff818b52a0    cpu_info_primary
r15                                0
rip               0xffffffff81346529    Debugger+0x9
cs                               0x8
rflags                         0x286
rsp               0xffff800022158b60
ss                              0x10
Debugger+0x9:   leave
ddb{0}>

Controller /dev/usb0:
addr 1: high speed, self powered, config 1, EHCI root hub(0x0000), Intel(0x8086), rev 1.00
 port 1 addr 2: high speed, self powered, config 1, Rate Matching Hub(0x0024), Intel(0x8087), rev 0.00
  port 1 powered
  port 2 powered
  port 3 powered
  port 4 powered
  port 5 powered
  port 6 addr 3: high speed, power 200 mA, config 1, USB DISK 2.0(0x3e00), (0x13fe), rev 1.00, iSerialNumber 07BB02020C6B02FC
 port 2 powered
Controller /dev/usb1:
addr 1: super speed, self powered, config 1, xHCI root hub(0x0000), Renesas(0x1912), rev 1.00
 port 1 disabled
 port 2 disabled
 port 3 disabled
 port 4 disabled
 port 5 disabled
 port 6 disabled
Controller /dev/usb2:
addr 1: full speed, self powered, config 1, UHCI root hub(0x0000), Hewlett-Packard(0x103c), rev 1.00
 port 1 powered
 port 2 powered
Controller /dev/usb3:
addr 1: high speed, self powered, config 1, EHCI root hub(0x0000), Intel(0x8086), rev 1.00
 port 1 addr 2: high speed, self powered, config 1, Rate Matching Hub(0x0024), Intel(0x8087), rev 0.00
  port 1 powered
  port 2 powered
  port 3 addr 3: high speed, self powered, config 1, product 0x2660(0x2660), Standard Microsystems(0x0424), rev 8.01
   port 1 addr 4: high speed, power 96 mA, config 1, Ultra Fast Media Reader(0x4030), Generic(0x0424), rev 2.09, iSerialNumber 000002660A01
   port 2 powered
  port 4 powered
  port 5 powered
  port 6 powered
 port 2 powered

Reply | Threaded
Open this post in threaded view
|

Re: kernel panic - panic: ehci_device_clear_toggle: queue active

Donald Allen
The crash I reported a few days ago is the same:
ehci_device_clear_toggle: queue active

Reply | Threaded
Open this post in threaded view
|

Re: kernel panic - panic: ehci_device_clear_toggle: queue active

Martin Pieuchot
In reply to this post by Björn Ketelaars
On 30/11/15(Mon) 18:28, Björn Ketelaars wrote:

> Hello,
>
> I repeatedly hit the kernel panic below. Easy to reproduce as it happens over
> and over again within 60 minutes after rebooting. Root cause is not known.
>
> I'm running snapshot on an USB stick. I tried different USB ports with the same
> result. Next step will be an attempt with a different USB stick.
>
> I think this issue has been mentioned before:
>
> https://marc.info/?t=141840591400001&r=1&w=3
> http://openbsd-archive.7691.n7.nabble.com/panic-ehci-device-clear-toggle-queue-active-td231729.html
> http://article.gmane.org/gmane.os.openbsd.bugs/19812/
>
> Any ideas on how to tackle this issue?

You can try the diff below and tell me if it helps.

Index: ehci.c
===================================================================
RCS file: /cvs/src/sys/dev/usb/ehci.c,v
retrieving revision 1.187
diff -u -p -r1.187 ehci.c
--- ehci.c 26 Jun 2015 11:17:34 -0000 1.187
+++ ehci.c 14 Oct 2015 14:24:19 -0000
@@ -188,12 +188,11 @@ int ehci_alloc_sitd_chain(struct ehci_s
 void ehci_abort_isoc_xfer(struct usbd_xfer *xfer,
     usbd_status status);
 
-usbd_status ehci_device_setintr(struct ehci_softc *, struct ehci_soft_qh *,
-    int ival);
+struct ehci_soft_qh * ehci_intr_get_sqh(struct usbd_pipe *);
 
-void ehci_add_qh(struct ehci_soft_qh *, struct ehci_soft_qh *);
-void ehci_rem_qh(struct ehci_softc *, struct ehci_soft_qh *);
-void ehci_set_qh_qtd(struct ehci_soft_qh *, struct ehci_soft_qtd *);
+void ehci_add_qh(struct usbd_pipe *, struct ehci_soft_qh *,
+    struct ehci_soft_qtd *);
+void ehci_rem_qh(struct ehci_softc *, struct usbd_pipe *);
 void ehci_sync_hc(struct ehci_softc *);
 
 void ehci_close_pipe(struct usbd_pipe *);
@@ -413,7 +412,6 @@ ehci_init(struct ehci_softc *sc)
  sqh->qh.qh_qtd.qtd_next = htole32(EHCI_LINK_TERMINATE);
  sqh->qh.qh_qtd.qtd_altnext = htole32(EHCI_LINK_TERMINATE);
  sqh->qh.qh_qtd.qtd_status = htole32(EHCI_QTD_HALTED);
- sqh->sqtd = NULL;
  usb_syncmem(&sqh->dma, sqh->offs, sizeof(sqh->qh),
     BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
  }
@@ -444,7 +442,6 @@ ehci_init(struct ehci_softc *sc)
  sqh->qh.qh_qtd.qtd_next = htole32(EHCI_LINK_TERMINATE);
  sqh->qh.qh_qtd.qtd_altnext = htole32(EHCI_LINK_TERMINATE);
  sqh->qh.qh_qtd.qtd_status = htole32(EHCI_QTD_HALTED);
- sqh->sqtd = NULL;
  usb_syncmem(&sqh->dma, sqh->offs, sizeof(sqh->qh),
     BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 
@@ -729,6 +726,7 @@ ehci_check_qh_intr(struct ehci_softc *sc
  return;
  }
  done:
+ ehci_rem_qh(sc, xfer->pipe);
  TAILQ_REMOVE(&sc->sc_intrhead, ex, inext);
  timeout_del(&xfer->timeout_handle);
  usb_rem_task(xfer->pipe->device, &xfer->abort_task);
@@ -861,7 +859,7 @@ ehci_idone(struct usbd_xfer *xfer)
 {
  struct ehci_xfer *ex = (struct ehci_xfer *)xfer;
  struct ehci_soft_qtd *sqtd;
- u_int32_t status = 0, nstatus = 0;
+ uint32_t status = 0, nstatus = 0;
  int actlen, cerr;
 
 #ifdef DIAGNOSTIC
@@ -1171,13 +1169,7 @@ ehci_freex(struct usbd_bus *bus, struct
 void
 ehci_device_clear_toggle(struct usbd_pipe *pipe)
 {
- struct ehci_pipe *epipe = (struct ehci_pipe *)pipe;
-
-#ifdef DIAGNOSTIC
- if ((epipe->sqh->qh.qh_qtd.qtd_status & htole32(EHCI_QTD_ACTIVE)) != 0)
- panic("ehci_device_clear_toggle: queue active");
-#endif
- epipe->sqh->qh.qh_qtd.qtd_status &= htole32(~EHCI_QTD_TOGGLE_MASK);
+ pipe->endpoint->savedtoggle = 0;
 }
 
 #ifdef EHCI_DEBUG
@@ -1374,29 +1366,17 @@ ehci_open(struct usbd_pipe *pipe)
  struct usbd_device *dev = pipe->device;
  struct ehci_softc *sc = (struct ehci_softc *)dev->bus;
  usb_endpoint_descriptor_t *ed = pipe->endpoint->edesc;
- u_int8_t addr = dev->address;
  u_int8_t xfertype = ed->bmAttributes & UE_XFERTYPE;
  struct ehci_pipe *epipe = (struct ehci_pipe *)pipe;
  struct ehci_soft_qh *sqh;
  usbd_status err;
- int s;
- int ival, speed, naks;
- int hshubaddr, hshubport;
 
- DPRINTFN(1, ("ehci_open: pipe=%p, addr=%d, endpt=%d\n",
+ DPRINTFN(1, ("%s: pipe=%p, addr=%d, endpt=%d\n", __func__,
     pipe, addr, ed->bEndpointAddress));
 
  if (sc->sc_bus.dying)
  return (USBD_IOERROR);
 
- if (dev->myhsport) {
- hshubaddr = dev->myhsport->parent->address;
- hshubport = dev->myhsport->portno;
- } else {
- hshubaddr = 0;
- hshubport = 0;
- }
-
  /* Root Hub */
  if (pipe->device->depth == 0) {
  switch (ed->bEndpointAddress) {
@@ -1412,55 +1392,11 @@ ehci_open(struct usbd_pipe *pipe)
  return (USBD_NORMAL_COMPLETION);
  }
 
- /* XXX All this stuff is only valid for async. */
- switch (dev->speed) {
- case USB_SPEED_LOW:
- speed = EHCI_QH_SPEED_LOW;
- break;
- case USB_SPEED_FULL:
- speed = EHCI_QH_SPEED_FULL;
- break;
- case USB_SPEED_HIGH:
- speed = EHCI_QH_SPEED_HIGH;
- break;
- default:
- panic("ehci_open: bad device speed %d", dev->speed);
- }
-
- naks = 8; /* XXX */
-
  /* Allocate sqh for everything, save isoc xfers */
  if (xfertype != UE_ISOCHRONOUS) {
  sqh = ehci_alloc_sqh(sc);
  if (sqh == NULL)
  return (USBD_NOMEM);
- /* qh_link filled when the QH is added */
- sqh->qh.qh_endp = htole32(
-    EHCI_QH_SET_ADDR(addr) |
-    EHCI_QH_SET_ENDPT(UE_GET_ADDR(ed->bEndpointAddress)) |
-    EHCI_QH_SET_EPS(speed) |
-    (xfertype == UE_CONTROL ? EHCI_QH_DTC : 0) |
-    EHCI_QH_SET_MPL(UGETW(ed->wMaxPacketSize)) |
-    (speed != EHCI_QH_SPEED_HIGH && xfertype == UE_CONTROL ?
-    EHCI_QH_CTL : 0) |
-    EHCI_QH_SET_NRL(naks)
-    );
- sqh->qh.qh_endphub = htole32(
-    EHCI_QH_SET_MULT(1) |
-    EHCI_QH_SET_HUBA(hshubaddr) |
-    EHCI_QH_SET_PORT(hshubport) |
-    EHCI_QH_SET_CMASK(0x1c) | /* XXX */
-    EHCI_QH_SET_SMASK(xfertype == UE_INTERRUPT ? 0x01 : 0)
-    );
- sqh->qh.qh_curqtd = htole32(EHCI_LINK_TERMINATE);
- /* Fill the overlay qTD */
- sqh->qh.qh_qtd.qtd_next = htole32(EHCI_LINK_TERMINATE);
- sqh->qh.qh_qtd.qtd_altnext = htole32(EHCI_LINK_TERMINATE);
- sqh->qh.qh_qtd.qtd_status =
-    htole32(EHCI_QTD_SET_TOGGLE(pipe->endpoint->savedtoggle));
-
- usb_syncmem(&sqh->dma, sqh->offs, sizeof(sqh->qh),
-    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
  epipe->sqh = sqh;
  } /*xfertype == UE_ISOC*/
 
@@ -1473,32 +1409,20 @@ ehci_open(struct usbd_pipe *pipe)
  return (err);
  }
  pipe->methods = &ehci_device_ctrl_methods;
- s = splusb();
- ehci_add_qh(sqh, sc->sc_async_head);
- splx(s);
  break;
  case UE_BULK:
  pipe->methods = &ehci_device_bulk_methods;
- s = splusb();
- ehci_add_qh(sqh, sc->sc_async_head);
- splx(s);
  break;
  case UE_INTERRUPT:
  pipe->methods = &ehci_device_intr_methods;
- ival = pipe->interval;
- if (ival == USBD_DEFAULT_INTERVAL)
- ival = ed->bInterval;
- s = splusb();
- err = ehci_device_setintr(sc, sqh, ival);
- splx(s);
- return (err);
+ break;
  case UE_ISOCHRONOUS:
- switch (speed) {
- case EHCI_QH_SPEED_HIGH:
- case EHCI_QH_SPEED_FULL:
+ switch (pipe->device->speed) {
+ case USB_SPEED_HIGH:
+ case USB_SPEED_FULL:
  pipe->methods = &ehci_device_isoc_methods;
  break;
- case EHCI_QH_SPEED_LOW:
+ case USB_SPEED_LOW:
  default:
  return (USBD_INVAL);
  }
@@ -1521,16 +1445,87 @@ ehci_open(struct usbd_pipe *pipe)
  return (USBD_NORMAL_COMPLETION);
 }
 
-/*
- * Add an ED to the schedule.  Called at splusb().
- * If in the async schedule, it will always have a next.
- * If in the intr schedule it may not.
- */
 void
-ehci_add_qh(struct ehci_soft_qh *sqh, struct ehci_soft_qh *head)
+ehci_add_qh(struct usbd_pipe *pipe, struct ehci_soft_qh *head,
+    struct ehci_soft_qtd *start)
 {
- SPLUSBCHECK;
+ struct ehci_pipe *epipe = (struct ehci_pipe *)pipe;
+ struct ehci_soft_qh *sqh = epipe->sqh;
+ usb_endpoint_descriptor_t *ed = pipe->endpoint->edesc;
+ uint8_t xfertype = ed->bmAttributes & UE_XFERTYPE;
+ uint8_t addr = pipe->device->address;
+ int i, hshubaddr, hshubport, speed;
+ int naks = 8; /* XXX */
+
+ KASSERT(xfertype != UE_ISOCHRONOUS);
+
+ splsoftassert(IPL_SOFTUSB);
+
+ if (pipe->device->myhsport) {
+ hshubaddr = pipe->device->myhsport->parent->address;
+ hshubport = pipe->device->myhsport->portno;
+ } else {
+ hshubaddr = 0;
+ hshubport = 0;
+ }
 
+ /* XXX All this stuff is only valid for async. */
+ switch (pipe->device->speed) {
+ case USB_SPEED_LOW:
+ speed = EHCI_QH_SPEED_LOW;
+ break;
+ case USB_SPEED_FULL:
+ speed = EHCI_QH_SPEED_FULL;
+ break;
+ case USB_SPEED_HIGH:
+ speed = EHCI_QH_SPEED_HIGH;
+ break;
+ default:
+ panic("%s: bad device speed %d", __func__, pipe->device->speed);
+ }
+
+ /* qh_link is filled below */
+ sqh->qh.qh_endp = htole32(
+    EHCI_QH_SET_ADDR(addr) |
+    EHCI_QH_SET_ENDPT(UE_GET_ADDR(ed->bEndpointAddress)) |
+    EHCI_QH_SET_EPS(speed) |
+    (xfertype == UE_CONTROL ? EHCI_QH_DTC : 0) |
+    EHCI_QH_SET_MPL(UGETW(ed->wMaxPacketSize)) |
+    (speed != EHCI_QH_SPEED_HIGH && xfertype == UE_CONTROL ?
+    EHCI_QH_CTL : 0) |
+    EHCI_QH_SET_NRL(naks)
+    );
+ sqh->qh.qh_endphub = htole32(
+    EHCI_QH_SET_MULT(1) |
+    EHCI_QH_SET_HUBA(hshubaddr) |
+    EHCI_QH_SET_PORT(hshubport) |
+    EHCI_QH_SET_CMASK(0x1c) | /* XXX */
+    EHCI_QH_SET_SMASK(xfertype == UE_INTERRUPT ? 0x01 : 0)
+    );
+ sqh->qh.qh_curqtd = 0;
+
+ sqh->qh.qh_qtd.qtd_next = htole32(start->physaddr);
+ sqh->qh.qh_qtd.qtd_altnext = htole32(EHCI_LINK_TERMINATE);
+ if (xfertype == UE_CONTROL)
+ sqh->qh.qh_qtd.qtd_status = 0;
+ else
+ sqh->qh.qh_qtd.qtd_status =
+    htole32(EHCI_QTD_SET_TOGGLE(pipe->endpoint->savedtoggle));
+
+ /* Reset reserved fields */
+ for (i = 0; i < EHCI_QTD_NBUFFERS; i++) {
+ sqh->qh.qh_qtd.qtd_buffer[i] = 0;
+ sqh->qh.qh_qtd.qtd_buffer_hi[i] = 0;
+ }
+ usb_syncmem(&sqh->dma, sqh->offs, sizeof(sqh->qh),
+    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
+
+ /*
+ * Add an ED to the schedule.
+ *
+ * If in the async schedule, it will always have a next.
+ * If in the intr schedule it may not.
+ */
  usb_syncmem(&head->dma, head->offs + offsetof(struct ehci_qh, qh_link),
     sizeof(head->qh.qh_link), BUS_DMASYNC_POSTWRITE);
  sqh->next = head->next;
@@ -1547,14 +1542,17 @@ ehci_add_qh(struct ehci_soft_qh *sqh, st
 }
 
 /*
- * Remove an ED from the schedule.  Called at splusb().
+ * Remove an ED from the schedule.
  * Will always have a 'next' if it's in the async list as it's circular.
  */
 void
-ehci_rem_qh(struct ehci_softc *sc, struct ehci_soft_qh *sqh)
+ehci_rem_qh(struct ehci_softc *sc, struct usbd_pipe *pipe)
 {
- SPLUSBCHECK;
- /* XXX */
+ struct ehci_pipe *epipe = (struct ehci_pipe *)pipe;
+ struct ehci_soft_qh *sqh = epipe->sqh;
+
+ splsoftassert(IPL_SOFTUSB);
+
  usb_syncmem(&sqh->dma, sqh->offs + offsetof(struct ehci_qh, qh_link),
     sizeof(sqh->qh.qh_link), BUS_DMASYNC_POSTWRITE);
  sqh->prev->qh.qh_link = sqh->qh.qh_link;
@@ -1565,42 +1563,8 @@ ehci_rem_qh(struct ehci_softc *sc, struc
     sqh->prev->offs + offsetof(struct ehci_qh, qh_link),
     sizeof(sqh->prev->qh.qh_link), BUS_DMASYNC_PREWRITE);
 
- ehci_sync_hc(sc);
-}
-
-void
-ehci_set_qh_qtd(struct ehci_soft_qh *sqh, struct ehci_soft_qtd *sqtd)
-{
- int i;
- u_int32_t status;
-
- /* Save toggle bit and ping status. */
- usb_syncmem(&sqh->dma, sqh->offs, sizeof(sqh->qh),
-    BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
- status = sqh->qh.qh_qtd.qtd_status &
-    htole32(EHCI_QTD_TOGGLE_MASK |
- EHCI_QTD_SET_STATUS(EHCI_QTD_PINGSTATE));
- /* Set HALTED to make hw leave it alone. */
- sqh->qh.qh_qtd.qtd_status =
-    htole32(EHCI_QTD_SET_STATUS(EHCI_QTD_HALTED));
- usb_syncmem(&sqh->dma,
-    sqh->offs + offsetof(struct ehci_qh, qh_qtd.qtd_status),
-    sizeof(sqh->qh.qh_qtd.qtd_status),
-    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
- sqh->qh.qh_curqtd = 0;
- sqh->qh.qh_qtd.qtd_next = htole32(sqtd->physaddr);
- sqh->qh.qh_qtd.qtd_altnext = htole32(EHCI_LINK_TERMINATE);
- for (i = 0; i < EHCI_QTD_NBUFFERS; i++)
- sqh->qh.qh_qtd.qtd_buffer[i] = 0;
- sqh->sqtd = sqtd;
- usb_syncmem(&sqh->dma, sqh->offs, sizeof(sqh->qh),
-    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
- /* Set !HALTED && !ACTIVE to start execution, preserve some fields */
- sqh->qh.qh_qtd.qtd_status = status;
- usb_syncmem(&sqh->dma,
-    sqh->offs + offsetof(struct ehci_qh, qh_qtd.qtd_status),
-    sizeof(sqh->qh.qh_qtd.qtd_status),
-    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
+ pipe->endpoint->savedtoggle =
+    EHCI_QTD_GET_TOGGLE(letoh32(sqh->qh.qh_qtd.qtd_status));
 }
 
 /*
@@ -2488,7 +2452,6 @@ ehci_alloc_sqtd_chain(struct ehci_softc
 void
 ehci_free_sqtd_chain(struct ehci_softc *sc, struct ehci_xfer *ex)
 {
- struct ehci_pipe *epipe = (struct ehci_pipe *)ex->xfer.pipe;
  struct ehci_soft_qtd *sqtd, *next;
 
  DPRINTFN(10,("ehci_free_sqtd_chain: sqtd=%p\n", ex->sqtdstart));
@@ -2498,7 +2461,6 @@ ehci_free_sqtd_chain(struct ehci_softc *
  ehci_free_sqtd(sc, sqtd);
  }
  ex->sqtdstart = ex->sqtdend = NULL;
- epipe->sqh->sqtd = NULL;
 }
 
 struct ehci_soft_itd *
@@ -2580,14 +2542,7 @@ ehci_close_pipe(struct usbd_pipe *pipe)
 {
  struct ehci_pipe *epipe = (struct ehci_pipe *)pipe;
  struct ehci_softc *sc = (struct ehci_softc *)pipe->device->bus;
- struct ehci_soft_qh *sqh = epipe->sqh;
- int s;
 
- s = splusb();
- ehci_rem_qh(sc, sqh);
- splx(s);
- pipe->endpoint->savedtoggle =
-    EHCI_QTD_GET_TOGGLE(letoh32(sqh->qh.qh_qtd.qtd_status));
  ehci_free_sqh(sc, epipe->sqh);
 }
 
@@ -2605,16 +2560,15 @@ void
 ehci_abort_xfer(struct usbd_xfer *xfer, usbd_status status)
 {
  struct ehci_softc *sc = (struct ehci_softc *)xfer->device->bus;
- struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->pipe;
  struct ehci_xfer *ex = (struct ehci_xfer*)xfer;
- struct ehci_soft_qh *sqh = epipe->sqh;
- struct ehci_soft_qtd *sqtd;
  int s;
 
  if (sc->sc_bus.dying || xfer->status == USBD_NOT_STARTED) {
  s = splusb();
- if (xfer->status != USBD_NOT_STARTED)
+ if (xfer->status != USBD_NOT_STARTED) {
+ ehci_rem_qh(sc, xfer->pipe);
  TAILQ_REMOVE(&sc->sc_intrhead, ex, inext);
+ }
  xfer->status = status; /* make software ignore it */
  timeout_del(&xfer->timeout_handle);
  usb_rem_task(xfer->device, &xfer->abort_task);
@@ -2647,51 +2601,21 @@ ehci_abort_xfer(struct usbd_xfer *xfer,
  return;
  }
 
- /*
- * Step 1: Make interrupt routine and timeouts ignore xfer.
- */
  s = splusb();
  ex->ehci_xfer_flags |= EHCI_XFER_ABORTING;
- xfer->status = status; /* make software ignore it */
+
+ /* Remove the Queue Head. */
+ ehci_rem_qh(sc, xfer->pipe);
  TAILQ_REMOVE(&sc->sc_intrhead, ex, inext);
+
+ xfer->status = status; /* make software ignore it */
  timeout_del(&xfer->timeout_handle);
  usb_rem_task(xfer->device, &xfer->abort_task);
- splx(s);
-
- /*
- * Step 2: Deactivate all of the qTDs that we will be removing,
- * otherwise the queue head may go active again.
- */
- usb_syncmem(&sqh->dma,
-    sqh->offs + offsetof(struct ehci_qh, qh_qtd.qtd_status),
-    sizeof(sqh->qh.qh_qtd.qtd_status),
-    BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
- sqh->qh.qh_qtd.qtd_status = htole32(EHCI_QTD_HALTED);
- usb_syncmem(&sqh->dma,
-    sqh->offs + offsetof(struct ehci_qh, qh_qtd.qtd_status),
-    sizeof(sqh->qh.qh_qtd.qtd_status),
-    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
-
- for (sqtd = ex->sqtdstart; sqtd != NULL; sqtd = sqtd->nextqtd) {
- usb_syncmem(&sqtd->dma,
-    sqtd->offs + offsetof(struct ehci_qtd, qtd_status),
-    sizeof(sqtd->qtd.qtd_status),
-    BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
- sqtd->qtd.qtd_status = htole32(EHCI_QTD_HALTED);
- usb_syncmem(&sqtd->dma,
-    sqtd->offs + offsetof(struct ehci_qtd, qtd_status),
-    sizeof(sqtd->qtd.qtd_status),
-    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
- }
- ehci_sync_hc(sc);
 
  /*
- * Step 3: Make sure the soft interrupt routine has run. This
+ * Make sure the soft interrupt routine has run. This
  * should remove any completed items off the queue.
- * The hardware has no reference to completed items (TDs).
- * It's safe to remove them at any time.
  */
- s = splusb();
  sc->sc_softwake = 1;
  usb_schedsoftintr(&sc->sc_bus);
  tsleep(&sc->sc_softwake, PZERO, "ehciab", 0);
@@ -2864,7 +2788,6 @@ ehci_device_ctrl_start(struct usbd_xfer
  struct ehci_xfer *ex = (struct ehci_xfer *)xfer;
  usb_device_request_t *req = &xfer->request;
  struct ehci_soft_qtd *setup, *stat, *next;
- struct ehci_soft_qh *sqh;
  u_int len = UGETW(req->wLength);
  usbd_status err;
  int s;
@@ -2885,8 +2808,6 @@ ehci_device_ctrl_start(struct usbd_xfer
  goto bad2;
  }
 
- sqh = epipe->sqh;
-
  /* Set up data transaction */
  if (len != 0) {
  struct ehci_soft_qtd *end;
@@ -2946,9 +2867,8 @@ ehci_device_ctrl_start(struct usbd_xfer
  ex->isdone = 0;
 #endif
 
- /* Insert qTD in QH list. */
  s = splusb();
- ehci_set_qh_qtd(sqh, setup);
+ ehci_add_qh(xfer->pipe, sc->sc_async_head, setup);
  if (xfer->timeout && !sc->sc_bus.use_polling) {
  timeout_del(&xfer->timeout_handle);
  timeout_set(&xfer->timeout_handle, ehci_timeout, xfer);
@@ -3016,10 +2936,8 @@ usbd_status
 ehci_device_bulk_start(struct usbd_xfer *xfer)
 {
  struct ehci_softc *sc = (struct ehci_softc *)xfer->device->bus;
- struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->pipe;
  struct ehci_xfer *ex = (struct ehci_xfer *)xfer;
  struct ehci_soft_qtd *data, *dataend;
- struct ehci_soft_qh *sqh;
  usbd_status err;
  int s;
 
@@ -3028,8 +2946,6 @@ ehci_device_bulk_start(struct usbd_xfer
  if (sc->sc_bus.dying)
  return (USBD_IOERROR);
 
- sqh = epipe->sqh;
-
  err = ehci_alloc_sqtd_chain(sc, xfer->length, xfer, &data, &dataend);
  if (err) {
  xfer->status = err;
@@ -3048,7 +2964,7 @@ ehci_device_bulk_start(struct usbd_xfer
 #endif
 
  s = splusb();
- ehci_set_qh_qtd(sqh, data);
+ ehci_add_qh(xfer->pipe, sc->sc_async_head, data);
  if (xfer->timeout && !sc->sc_bus.use_polling) {
  timeout_del(&xfer->timeout_handle);
  timeout_set(&xfer->timeout_handle, ehci_timeout, xfer);
@@ -3093,12 +3009,18 @@ ehci_device_bulk_done(struct usbd_xfer *
  }
 }
 
-usbd_status
-ehci_device_setintr(struct ehci_softc *sc, struct ehci_soft_qh *sqh, int ival)
+struct ehci_soft_qh *
+ehci_intr_get_sqh(struct usbd_pipe *pipe)
 {
+ struct ehci_softc *sc = (struct ehci_softc *)pipe->device->bus;
+ struct ehci_pipe *epipe = (struct ehci_pipe *)pipe;
  struct ehci_soft_islot *isp;
+ int ival = pipe->interval;
  int islot, lev;
 
+ if (ival == USBD_DEFAULT_INTERVAL)
+ ival = pipe->endpoint->edesc->bInterval;
+
  /* Find a poll rate that is large enough. */
  for (lev = EHCI_IPOLLRATES - 1; lev > 0; lev--)
  if (EHCI_ILEV_IVAL(lev) <= ival)
@@ -3108,11 +3030,10 @@ ehci_device_setintr(struct ehci_softc *s
  /* XXX could do better than picking at random */
  islot = EHCI_IQHIDX(lev, arc4random());
 
- sqh->islot = islot;
+ epipe->sqh->islot = islot;
  isp = &sc->sc_islots[islot];
- ehci_add_qh(sqh, isp->sqh);
 
- return (USBD_NORMAL_COMPLETION);
+ return (isp->sqh);
 }
 
 usbd_status
@@ -3137,9 +3058,7 @@ ehci_device_intr_start(struct usbd_xfer
 {
  struct ehci_softc *sc = (struct ehci_softc *)xfer->device->bus;
  struct ehci_xfer *ex = (struct ehci_xfer *)xfer;
- struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->pipe;
  struct ehci_soft_qtd *data, *dataend;
- struct ehci_soft_qh *sqh;
  usbd_status err;
  int s;
 
@@ -3148,8 +3067,6 @@ ehci_device_intr_start(struct usbd_xfer
  if (sc->sc_bus.dying)
  return (USBD_IOERROR);
 
- sqh = epipe->sqh;
-
  err = ehci_alloc_sqtd_chain(sc, xfer->length, xfer, &data, &dataend);
  if (err) {
  xfer->status = err;
@@ -3167,7 +3084,7 @@ ehci_device_intr_start(struct usbd_xfer
 #endif
 
  s = splusb();
- ehci_set_qh_qtd(sqh, data);
+ ehci_add_qh(xfer->pipe, ehci_intr_get_sqh(xfer->pipe), data);
  if (xfer->timeout && !sc->sc_bus.use_polling) {
  timeout_del(&xfer->timeout_handle);
  timeout_set(&xfer->timeout_handle, ehci_timeout, xfer);
@@ -3206,48 +3123,15 @@ void
 ehci_device_intr_done(struct usbd_xfer *xfer)
 {
  struct ehci_softc *sc = (struct ehci_softc *)xfer->device->bus;
- struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->pipe;
  struct ehci_xfer *ex = (struct ehci_xfer *)xfer;
- struct ehci_soft_qtd *data, *dataend;
- struct ehci_soft_qh *sqh;
- usbd_status err;
- int s;
 
  if (xfer->pipe->repeat) {
  ehci_free_sqtd_chain(sc, ex);
-
  usb_syncmem(&xfer->dmabuf, 0, xfer->length,
     usbd_xfer_isread(xfer) ?
     BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
- sqh = epipe->sqh;
-
- err = ehci_alloc_sqtd_chain(sc, xfer->length, xfer, &data, &dataend);
- if (err) {
- xfer->status = err;
- return;
- }
-
- /* Set up interrupt info. */
- ex->sqtdstart = data;
- ex->sqtdend = dataend;
-#ifdef DIAGNOSTIC
- if (!ex->isdone) {
- printf("ehci_device_intr_done: not done, ex=%p\n",
- ex);
- }
- ex->isdone = 0;
-#endif
 
- s = splusb();
- ehci_set_qh_qtd(sqh, data);
- if (xfer->timeout && !sc->sc_bus.use_polling) {
- timeout_del(&xfer->timeout_handle);
- timeout_set(&xfer->timeout_handle, ehci_timeout, xfer);
- timeout_add_msec(&xfer->timeout_handle, xfer->timeout);
- }
- TAILQ_INSERT_TAIL(&sc->sc_intrhead, ex, inext);
- xfer->status = USBD_IN_PROGRESS;
- splx(s);
+ ehci_device_intr_start(xfer);
  } else if (xfer->status != USBD_NOMEM) {
  ehci_free_sqtd_chain(sc, ex);
  usb_syncmem(&xfer->dmabuf, 0, xfer->length,
Index: ehcivar.h
===================================================================
RCS file: /cvs/src/sys/dev/usb/ehcivar.h,v
retrieving revision 1.35
diff -u -p -r1.35 ehcivar.h
--- ehcivar.h 10 Apr 2015 13:56:42 -0000 1.35
+++ ehcivar.h 29 Sep 2015 10:50:28 -0000
@@ -46,7 +46,6 @@ struct ehci_soft_qh {
  struct ehci_qh qh;
  struct ehci_soft_qh *next;
  struct ehci_soft_qh *prev;
- struct ehci_soft_qtd *sqtd;
  ehci_physaddr_t physaddr;
  struct usb_dma dma;             /* QH's DMA infos */
  int offs;                       /* QH's offset in struct usb_dma */

Reply | Threaded
Open this post in threaded view
|

Re: kernel panic - panic: ehci_device_clear_toggle: queue active

Björn Ketelaars
On Thu 03/12/2015 09:54, Martin Pieuchot wrote:

> On 30/11/15(Mon) 18:28, Björn Ketelaars wrote:
> > Hello,
> >
> > I repeatedly hit the kernel panic below. Easy to reproduce as it happens over
> > and over again within 60 minutes after rebooting. Root cause is not known.
> >
> > I'm running snapshot on an USB stick. I tried different USB ports with the same
> > result. Next step will be an attempt with a different USB stick.
> >
> > I think this issue has been mentioned before:
> >
> > https://marc.info/?t=141840591400001&r=1&w=3
> > http://openbsd-archive.7691.n7.nabble.com/panic-ehci-device-clear-toggle-queue-active-td231729.html
> > http://article.gmane.org/gmane.os.openbsd.bugs/19812/
> >
> > Any ideas on how to tackle this issue?
>
> You can try the diff below and tell me if it helps.
>
> Index: ehci.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/usb/ehci.c,v
> retrieving revision 1.187
> diff -u -p -r1.187 ehci.c
> --- ehci.c 26 Jun 2015 11:17:34 -0000 1.187
> +++ ehci.c 14 Oct 2015 14:24:19 -0000
>

Yes, it helps!

I build and installed a new kernel using your diff and tested it with a couple
of USB-sticks on different USB-ports. No panics...
Reverting to an old (unpatched) kernel, using the above routine, soon resulted
in a hang.

I'm currently running a kernel with your diff. As stated: it helps.

Thanks!