From 0f0a1880cf345acba4cad24a419e25de469de03e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=BCrgen=20Wall?= <fakeEmail@fakesite.fake>
Date: Thu, 4 Oct 2012 21:17:45 +0000
Subject: [PATCH] Fix ownership handover from SMM to OS.
* Disabling all interrupts prior to ownership handover from SMM to OS
can prevent propper OHCI and PS/2 functionality as described in
#8987 and #8984. In that case SMM does not respond to the ownership
change request. On the other hand not disabling the interrupts can
lead to interrupt storms (discussed in #8085) since no interrupt
handler is installed at that moment. As suggested by mmlr this patch
attempts to address both issues by keeping the ownership change
request interrupt enabled.
* Removed an unnecessary reset upon non-responding SMM for now,
since we reset a few lines later anyway and added TODOs respectively.
That should safe a bit boot time.
---
src/add-ons/kernel/busses/usb/ohci.cpp | 24 +++++++++++++++++-------
1 file changed, 17 insertions(+), 7 deletions(-)
diff --git a/src/add-ons/kernel/busses/usb/ohci.cpp b/src/add-ons/kernel/busses/usb/ohci.cpp
index df38174..73bc769 100644
a
|
b
|
OHCI::OHCI(pci_info *info, Stack *stack)
|
206 | 206 | fInterruptEndpoints[0]->next_physical_endpoint |
207 | 207 | = fDummyIsochronous->physical_address; |
208 | 208 | |
209 | | // Disable all interrupts before handoff/reset |
210 | | _WriteReg(OHCI_INTERRUPT_DISABLE, OHCI_ALL_INTERRUPTS); |
| 209 | // When the handover from SMM takes place, all interrupts are routed to the |
| 210 | // OS. As we don't yet have an interrupt handler installed at this point, |
| 211 | // this may cause interrupt storms if the firmware does not disable the |
| 212 | // interrupts during handover. Therefore we disable interrupts before |
| 213 | // requesting ownership. We have to keep the ownership change interrupt |
| 214 | // enabled though, as otherwise the SMM will not be notified of the |
| 215 | // ownership change request we trigger below. |
| 216 | _WriteReg(OHCI_INTERRUPT_DISABLE, OHCI_ALL_INTERRUPTS & |
| 217 | ~OHCI_OWNERSHIP_CHANGE) ; |
211 | 218 | |
212 | 219 | // Determine in what context we are running (Kindly copied from FreeBSD) |
213 | 220 | uint32 control = _ReadReg(OHCI_CONTROL); |
… |
… |
OHCI::OHCI(pci_info *info, Stack *stack)
|
221 | 228 | } |
222 | 229 | |
223 | 230 | if ((control & OHCI_INTERRUPT_ROUTING) != 0) { |
224 | | TRACE_ERROR("smm does not respond. resetting...\n"); |
225 | | _WriteReg(OHCI_CONTROL, OHCI_HC_FUNCTIONAL_STATE_RESET); |
226 | | snooze(USB_DELAY_BUS_RESET); |
| 231 | TRACE_ERROR("smm does not respond.\n"); |
| 232 | |
| 233 | // TODO: Enable this reset as soon as the non-specified |
| 234 | // reset a few lines later is replaced by a better solution. |
| 235 | //_WriteReg(OHCI_CONTROL, OHCI_HC_FUNCTIONAL_STATE_RESET); |
| 236 | //snooze(USB_DELAY_BUS_RESET); |
227 | 237 | } else |
228 | 238 | TRACE_ALWAYS("ownership change successful\n"); |
229 | 239 | } else { |
… |
… |
OHCI::OHCI(pci_info *info, Stack *stack)
|
231 | 241 | snooze(USB_DELAY_BUS_RESET); |
232 | 242 | } |
233 | 243 | |
234 | | // This reset should not be necessary according to the OHCI spec, but |
235 | | // without it some controllers do not start. |
| 244 | // TODO: This reset delays system boot time. It should not be necessary |
| 245 | // according to the OHCI spec, but without it some controllers don't start. |
236 | 246 | _WriteReg(OHCI_CONTROL, OHCI_HC_FUNCTIONAL_STATE_RESET); |
237 | 247 | snooze(USB_DELAY_BUS_RESET); |
238 | 248 | |