[haiku-commits] haiku: hrev50378 - src/add-ons/kernel/busses/usb

  • From: jerome.duval@xxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Thu, 30 Jun 2016 12:20:47 +0200 (CEST)

hrev50378 adds 1 changeset to branch 'master'
old head: 089305fcdc83372e3a8c93a4dbe7feaab64243f9
new head: 936696c78a28791dd33597fe47ea35bcdb58c2b8
overview: 
http://cgit.haiku-os.org/haiku/log/?qt=range&q=936696c78a28+%5E089305fcdc83

----------------------------------------------------------------------------

936696c78a28: XHCI: fix handling of transfer events.
  
  * previously processing of transfer began when an event on the transfer 
descriptor happened. Now wait until the last TRB to be processed to process and 
free the descriptor. Chains are probably not handled correcly yet, but usual 
transfers happen on a single TD.
  * use a specific link pointer for transfer descriptor chains.
  * tested on VirtualBox passthrough with mounting an external SSD enclosure. 
It doesn't scale well with SMP: 1CPU ~115MB/s, 2CPU ~65MB/s, 4 CPU ~50MB/s.
  * whitelist controller Intel product ID 0x1e31 (found on VB5).

                                   [ Jérôme Duval <jerome.duval@xxxxxxxxx> ]

----------------------------------------------------------------------------

Revision:    hrev50378
Commit:      936696c78a28791dd33597fe47ea35bcdb58c2b8
URL:         http://cgit.haiku-os.org/haiku/commit/?id=936696c78a28
Author:      Jérôme Duval <jerome.duval@xxxxxxxxx>
Date:        Thu Jun 30 09:56:36 2016 UTC

----------------------------------------------------------------------------

2 files changed, 50 insertions(+), 33 deletions(-)
src/add-ons/kernel/busses/usb/xhci.cpp | 82 ++++++++++++++++++------------
src/add-ons/kernel/busses/usb/xhci.h   |  1 +

----------------------------------------------------------------------------

diff --git a/src/add-ons/kernel/busses/usb/xhci.cpp 
b/src/add-ons/kernel/busses/usb/xhci.cpp
index eedcf7b..b2baa19 100644
--- a/src/add-ons/kernel/busses/usb/xhci.cpp
+++ b/src/add-ons/kernel/busses/usb/xhci.cpp
@@ -373,7 +373,7 @@ XHCI::_SwitchIntelPorts()
 status_t
 XHCI::Start()
 {
-       TRACE("starting XHCI host controller\n");
+       TRACE_ALWAYS("starting XHCI host controller\n");
        TRACE("usbcmd: 0x%08" B_PRIx32 "; usbsts: 0x%08" B_PRIx32 "\n",
                ReadOpReg(XHCI_CMD), ReadOpReg(XHCI_STS));
 
@@ -640,12 +640,12 @@ XHCI::SubmitControlRequest(Transfer *transfer)
 
        TRACE("SubmitControlRequest() request linked\n");
 
-       TRACE("Endpoint status 0x%" B_PRIx32 " 0x%" B_PRIx32 " 0x%" B_PRIx64 
"\n",
+       TRACE("Endpoint status 0x%08" B_PRIx32 " 0x%08" B_PRIx32 " 0x%016" 
B_PRIx64 "\n",
                endpoint->device->device_ctx->endpoints[id-1].dwendpoint0,
                endpoint->device->device_ctx->endpoints[id-1].dwendpoint1,
                endpoint->device->device_ctx->endpoints[id-1].qwendpoint2);
        Ring(endpoint->device->slot, id);
-       TRACE("Endpoint status 0x%" B_PRIx32 " 0x%" B_PRIx32 " 0x%" B_PRIx64 
"\n",
+       TRACE("Endpoint status 0x%08" B_PRIx32 " 0x%08" B_PRIx32 " 0x%016" 
B_PRIx64 "\n",
                endpoint->device->device_ctx->endpoints[id-1].dwendpoint0,
                endpoint->device->device_ctx->endpoints[id-1].dwendpoint1,
                endpoint->device->device_ctx->endpoints[id-1].qwendpoint2);
@@ -697,16 +697,15 @@ XHCI::SubmitNormalRequest(Transfer *transfer)
 
        TRACE("SubmitNormalRequest() request linked\n");
 
-       TRACE("Endpoint status 0x%" B_PRIx32 " 0x%" B_PRIx32 " 0x%" B_PRIx64 
"\n",
+       TRACE("Endpoint status 0x%08" B_PRIx32 " 0x%08" B_PRIx32 " 0x%016" 
B_PRIx64 "\n",
                endpoint->device->device_ctx->endpoints[id - 1].dwendpoint0,
                endpoint->device->device_ctx->endpoints[id - 1].dwendpoint1,
                endpoint->device->device_ctx->endpoints[id - 1].qwendpoint2);
        Ring(endpoint->device->slot, id);
-       TRACE("Endpoint status 0x%" B_PRIx32 " 0x%" B_PRIx32 " 0x%" B_PRIx64 
"\n",
+       TRACE("Endpoint status 0x%08" B_PRIx32 " 0x%08" B_PRIx32 " 0x%016" 
B_PRIx64 "\n",
                endpoint->device->device_ctx->endpoints[id - 1].dwendpoint0,
                endpoint->device->device_ctx->endpoints[id - 1].dwendpoint1,
                endpoint->device->device_ctx->endpoints[id - 1].qwendpoint2);
-
        return B_OK;
 }
 
@@ -714,6 +713,8 @@ XHCI::SubmitNormalRequest(Transfer *transfer)
 status_t
 XHCI::CancelQueuedTransfers(Pipe *pipe, bool force)
 {
+       TRACE_ALWAYS("cancel queued transfers for pipe %p (%d)\n", pipe,
+               pipe->EndpointAddress());
        return B_OK;
 }
 
@@ -790,6 +791,7 @@ XHCI::AddTo(Stack *stack)
                        switch ((item->vendor_id << 16) | item->device_id) {
                                case 0x10330194:        // Nec Corporation 
uPD720200
                                case 0x1b731009:        // Fresco Logic FL1009
+                               case 0x80861e31:        // Intel xHCI found on 
VirtualBox5.
                                        break;
                                default:
                                        TRACE_MODULE_ERROR("found device but 
unsupported\n");
@@ -873,7 +875,7 @@ XHCI::CreateDescriptorChain(size_t bufferSize)
                descriptor->buffer_count = trbs;
                trbCount -= trbs;
                if (last != NULL)
-                       last->next = descriptor;
+                       last->next_chain = descriptor;
                last = descriptor;
        }
 
@@ -981,7 +983,7 @@ XHCI::WriteDescriptorChain(xhci_td *descriptor, iovec 
*vector,
                        }
                }
 
-               current = current->next;
+               current = current->next_chain;
                trbIndex = 0;
        }
 
@@ -1036,7 +1038,7 @@ XHCI::ReadDescriptorChain(xhci_td *descriptor, iovec 
*vector,
                        }
                }
 
-               current = current->next;
+               current = current->next_chain;
                trbIndex = 0;
        }
 
@@ -1147,7 +1149,7 @@ XHCI::AllocateDevice(Hub *parent, int8 hubAddress, uint8 
hubPort,
        device->input_ctx->slot.dwslot3 = SLOT_3_SLOT_STATE(0)
                | SLOT_3_DEVICE_ADDRESS(0);
 
-       TRACE("slot 0x%" B_PRIx32 " 0x%" B_PRIx32 " 0x%" B_PRIx32 " 0x%" 
B_PRIx32
+       TRACE("slot 0x%08" B_PRIx32 " 0x%08" B_PRIx32 " 0x%08" B_PRIx32 " 
0x%08" B_PRIx32
                "\n", device->input_ctx->slot.dwslot0,
                device->input_ctx->slot.dwslot1, 
device->input_ctx->slot.dwslot2,
                device->input_ctx->slot.dwslot3);
@@ -1224,9 +1226,9 @@ XHCI::AllocateDevice(Hub *parent, int8 hubAddress, uint8 
hubPort,
        device->address = SLOT_3_DEVICE_ADDRESS_GET(
                device->device_ctx->slot.dwslot3);
 
-       TRACE("device: address 0x%x state 0x%" B_PRIx32 "\n", device->address,
+       TRACE("device: address 0x%x state 0x%08" B_PRIx32 "\n", device->address,
                SLOT_3_SLOT_STATE_GET(device->device_ctx->slot.dwslot3));
-       TRACE("endpoint0 state 0x%" B_PRIx32 "\n",
+       TRACE("endpoint0 state 0x%08" B_PRIx32 "\n",
                
ENDPOINT_0_STATE_GET(device->device_ctx->endpoints[0].dwendpoint0));
 
        // Create a temporary pipe with the new address
@@ -1396,12 +1398,13 @@ XHCI::_InsertEndpointForPipe(Pipe *pipe)
 
                uint8 endpoint = id + 1;
 
+               /* TODO: invalid Context State running the 3 following commands
                StopEndpoint(false, endpoint, device->slot);
 
                ResetEndpoint(false, endpoint, device->slot);
 
                SetTRDequeue(device->endpoints[id].trb_addr, 0, endpoint,
-                       device->slot);
+                       device->slot); */
 
                device->input_ctx->input.dropFlags = 0;
                device->input_ctx->input.addFlags = (1 << endpoint) | (1 << 0);
@@ -1429,11 +1432,11 @@ XHCI::_InsertEndpointForPipe(Pipe *pipe)
                EvaluateContext(device->input_ctx_addr, device->slot);
 
                ConfigureEndpoint(device->input_ctx_addr, false, device->slot);
-               TRACE("device: address 0x%x state 0x%" B_PRIx32 "\n", 
device->address,
+               TRACE("device: address 0x%x state 0x%08" B_PRIx32 "\n", 
device->address,
                        
SLOT_3_SLOT_STATE_GET(device->device_ctx->slot.dwslot3));
-               TRACE("endpoint[0] state 0x%" B_PRIx32 "\n",
+               TRACE("endpoint[0] state 0x%08" B_PRIx32 "\n",
                        
ENDPOINT_0_STATE_GET(device->device_ctx->endpoints[0].dwendpoint0));
-               TRACE("endpoint[%d] state 0x%" B_PRIx32 "\n", id,
+               TRACE("endpoint[%d] state 0x%08" B_PRIx32 "\n", id,
                        
ENDPOINT_0_STATE_GET(device->device_ctx->endpoints[id].dwendpoint0));
                device->state = XHCI_STATE_CONFIGURED;
        }
@@ -1461,7 +1464,7 @@ XHCI::_LinkDescriptorForPipe(xhci_td *descriptor, 
xhci_endpoint *endpoint)
 {
        TRACE("_LinkDescriptorForPipe\n");
        MutexLocker endpointLocker(endpoint->lock);
-       if (endpoint->used > XHCI_MAX_TRANSFERS) {
+       if (endpoint->used >= XHCI_MAX_TRANSFERS) {
                TRACE_ERROR("_LinkDescriptorForPipe max transfers count 
exceeded\n");
                return B_BAD_VALUE;
        }
@@ -1495,7 +1498,7 @@ XHCI::_LinkDescriptorForPipe(xhci_td *descriptor, 
xhci_endpoint *endpoint)
                | TRB_3_CYCLE_BIT;
 
        TRACE("_LinkDescriptorForPipe pCurrent %p phys 0x%" B_PRIxPHYSADDR
-               " 0x%" B_PRIxPHYSADDR " 0x%" B_PRIx32 "\n", 
&endpoint->trbs[current],
+               " 0x%" B_PRIxPHYSADDR " 0x%08" B_PRIx32 "\n", 
&endpoint->trbs[current],
                endpoint->trb_addr + current * sizeof(struct xhci_trb),
                endpoint->trbs[current].qwtrb0, endpoint->trbs[current].dwtrb3);
        endpoint->current = next;
@@ -1962,22 +1965,35 @@ XHCI::HandleTransferComplete(xhci_trb* trb)
 
        xhci_device *device = &fDevices[slot];
        xhci_endpoint *endpoint = &device->endpoints[endpointNumber - 1];
-       for (xhci_td *td = endpoint->td_head; td != NULL; td = td->next) {
-               int64 offset = source - td->this_phy;
-               TRACE("HandleTransferComplete td %p offset %" B_PRId64 "\n", td,
-                       offset);
-               (void)offset;
-               _UnlinkDescriptorForPipe(td, endpoint);
-               td->trb_completion_code = completionCode;
-               td->trb_left = remainder;
-               // add descriptor to finished list (to be processed and freed)
-               Lock();
-               td->next = fFinishedHead;
-               fFinishedHead = td;
-               Unlock();
-               release_sem(fFinishTransfersSem);
-               break;
+       xhci_td *td = endpoint->td_head;
+       for (; td != NULL; td = td->next) {
+               xhci_td *td_chain = td;
+               for (; td_chain != NULL; td_chain = td_chain->next_chain) {
+                       int64 offset = source - td_chain->this_phy;
+                       TRACE("HandleTransferComplete td %p offset %" B_PRId64 
" %"
+                               B_PRIx64 "\n", td_chain, offset, source);
+                       offset = offset / sizeof(xhci_trb);
+                       if (offset <= td_chain->trb_count && offset >= 0) {
+                               TRACE("HandleTransferComplete td %p trb %" 
B_PRId64 " found "
+                                       "\n", td_chain, offset);
+                               // is it the last trb?
+                               if (offset == td_chain->trb_count) {
+                                       _UnlinkDescriptorForPipe(td, endpoint);
+                                       td->trb_completion_code = 
completionCode;
+                                       td->trb_left = remainder;
+                                       // add descriptor to finished list
+                                       Lock();
+                                       td->next = fFinishedHead;
+                                       fFinishedHead = td;
+                                       Unlock();
+                                       release_sem(fFinishTransfersSem);
+                                       TRACE("HandleTransferComplete td %p\n", 
td);
+                               }
+                               return;
+                       }
+               }
        }
+
 }
 
 
diff --git a/src/add-ons/kernel/busses/usb/xhci.h 
b/src/add-ons/kernel/busses/usb/xhci.h
index 3657c0c..de84a82 100644
--- a/src/add-ons/kernel/busses/usb/xhci.h
+++ b/src/add-ons/kernel/busses/usb/xhci.h
@@ -42,6 +42,7 @@ typedef struct xhci_td {
        size_t  buffer_size[XHCI_MAX_TRBS_PER_TD];      // Size of the buffer
        uint8   buffer_count;
 
+       struct xhci_td  *next_chain;
        struct xhci_td  *next;
        Transfer *transfer;
        uint8   trb_count;


Other related posts: