From 955dc88f0c0225985a695689d675e0c119a1bdc4 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Sat, 6 Jan 2007 18:05:05 +0000 Subject: [PATCH] * Fixed spinlock usage in EHCI and UHCI drivers * Fixed UHCI to allow for empty transfer buffers * Extended the check for still linked transfer descriptors when removing a chain There remain UHCI bugs that will cause transfers outgoing transfers to fail. I'll have to review / rewrite the UHCI driver. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@19730 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/add-ons/kernel/busses/usb/ehci.cpp | 2 +- src/add-ons/kernel/busses/usb/uhci.cpp | 34 +++++++++++++------------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/add-ons/kernel/busses/usb/ehci.cpp b/src/add-ons/kernel/busses/usb/ehci.cpp index 8b3a645dda..d05400712f 100644 --- a/src/add-ons/kernel/busses/usb/ehci.cpp +++ b/src/add-ons/kernel/busses/usb/ehci.cpp @@ -762,7 +762,7 @@ EHCI::InterruptHandler(void *data) int32 EHCI::Interrupt() { - spinlock lock = 0; + static spinlock lock = 0; acquire_spinlock(&lock); // check if any interrupt was generated diff --git a/src/add-ons/kernel/busses/usb/uhci.cpp b/src/add-ons/kernel/busses/usb/uhci.cpp index 0913965f79..c37e6a639d 100644 --- a/src/add-ons/kernel/busses/usb/uhci.cpp +++ b/src/add-ons/kernel/busses/usb/uhci.cpp @@ -226,6 +226,8 @@ Queue::AppendDescriptorChain(uhci_td *descriptor) element->link_log = descriptor; element->link_phy = descriptor->this_phy | TD_DEPTH_FIRST; + if (fQueueHead->element_phy & QH_TERMINATE) + fQueueHead->element_phy = descriptor->this_phy; TRACE(("usb_uhci: appended transfer to queue\n")); } @@ -247,11 +249,9 @@ Queue::RemoveDescriptorChain(uhci_td *firstDescriptor, uhci_td *lastDescriptor) if ((lastDescriptor->link_phy & TD_TERMINATE) > 0) { // it is the only chain in this queue fQueueTop = NULL; - fQueueHead->element_phy = QH_TERMINATE; } else { // there are still linked transfers fQueueTop = (uhci_td *)lastDescriptor->link_log; - fQueueHead->element_phy = fQueueTop->this_phy & TD_LINK_MASK; } } else { // unlink the chain @@ -265,16 +265,17 @@ Queue::RemoveDescriptorChain(uhci_td *firstDescriptor, uhci_td *lastDescriptor) element = (uhci_td *)element->link_log; } + } - element = firstDescriptor; - while (element && element != lastDescriptor) { - if ((fQueueHead->element_phy & TD_LINK_MASK) == element->this_phy) { - fQueueHead->element_phy = lastDescriptor->link_phy; - break; - } - - element = (uhci_td *)element->link_log; + uhci_td *element = firstDescriptor; + while (element && element != lastDescriptor->link_log) { + if ((fQueueHead->element_phy & TD_LINK_MASK) == element->this_phy) { + fQueueHead->element_phy = lastDescriptor->link_phy; + TRACE_ERROR(("uhci: queue element pointer still pointing to removed chain\n")); + break; } + + element = (uhci_td *)element->link_log; } lastDescriptor->link_log = NULL; @@ -357,8 +358,8 @@ UHCI::UHCI(pci_info *info, Stack *stack) fPCIInfo->function, PCI_command, 2, command); // make sure we gain control of the UHCI controller instead of the BIOS - sPCIModule->write_pci_config(fPCIInfo->bus, fPCIInfo->device, fPCIInfo->function, - PCI_LEGSUP, 2, PCI_LEGSUP_USBPIRQDEN); + sPCIModule->write_pci_config(fPCIInfo->bus, fPCIInfo->device, + fPCIInfo->function, PCI_LEGSUP, 2, PCI_LEGSUP_USBPIRQDEN); // disable interrupts WriteReg16(UHCI_USBINTR, 0); @@ -523,9 +524,6 @@ UHCI::SubmitTransfer(Transfer *transfer) if (transfer->TransferPipe()->Type() & USB_OBJECT_CONTROL_PIPE) return SubmitRequest(transfer); - if (transfer->VectorCount() == 0) - return B_BAD_VALUE; - Pipe *pipe = transfer->TransferPipe(); bool directionIn = (pipe->Direction() == Pipe::In); @@ -714,7 +712,7 @@ UHCI::AddPendingTransfer(Transfer *transfer, Queue *queue, if (fLastTransfer) fLastTransfer->link = data; - else + if (!fFirstTransfer) fFirstTransfer = data; fLastTransfer = data; @@ -1073,7 +1071,7 @@ UHCI::InterruptHandler(void *data) int32 UHCI::Interrupt() { - spinlock lock = 0; + static spinlock lock = 0; acquire_spinlock(&lock); // Check if we really had an interrupt @@ -1259,6 +1257,8 @@ UHCI::CreateDescriptorChain(Pipe *pipe, uhci_td **_firstDescriptor, { size_t packetSize = pipe->MaxPacketSize(); int32 descriptorCount = (bufferSize + packetSize - 1) / packetSize; + if (descriptorCount == 0) + descriptorCount = 1; bool dataToggle = pipe->DataToggle(); uhci_td *firstDescriptor = NULL;