[haiku-commits] haiku: hrev53137 - in src/add-ons/kernel: busses/usb bus_managers/usb

  • From: waddlesplash <waddlesplash@xxxxxxxxx>
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Thu, 16 May 2019 20:47:19 -0400 (EDT)

hrev53137 adds 1 changeset to branch 'master'
old head: c8836afc0a2bebbfb34b7d71448cc372bdeea972
new head: 086528f66af8e1f420be92d2af971605554e5264
overview: 
https://git.haiku-os.org/haiku/log/?qt=range&q=086528f66af8+%5Ec8836afc0a2b

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

086528f66af8: USB & XHCI: Refactor endpoint initialization to support 
SuperSpeed better.
  
  SuperSpeed (USB3) devices have a "companion descriptor" along with the
  endpoint descriptors that describes certain other attributes they have,
  which are important for the controller to schedule transfers properly.
  Previously we were just using USB2 values; now we are properly using USB3
  ones.
  
  Tested on an Intel Lynx Point controller. As far as I can tell, no
  regressions, but #15000 is not fixed anyway.

                              [ Augustin Cavalier <waddlesplash@xxxxxxxxx> ]

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

Revision:    hrev53137
Commit:      086528f66af8e1f420be92d2af971605554e5264
URL:         https://git.haiku-os.org/haiku/commit/?id=086528f66af8
Author:      Augustin Cavalier <waddlesplash@xxxxxxxxx>
Date:        Fri May 17 00:31:11 2019 UTC

Ticket:      https://dev.haiku-os.org/ticket/15000

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

7 files changed, 102 insertions(+), 31 deletions(-)
src/add-ons/kernel/bus_managers/usb/Device.cpp   | 43 ++++++++++++++++++++
src/add-ons/kernel/bus_managers/usb/Pipe.cpp     | 11 +++++
.../kernel/bus_managers/usb/usb_private.h        | 10 +++++
.../kernel/bus_managers/usb/usbspec_private.h    | 11 +++++
src/add-ons/kernel/busses/usb/xhci.cpp           | 42 ++++++++++---------
src/add-ons/kernel/busses/usb/xhci.h             |  3 +-
src/add-ons/kernel/busses/usb/xhci_rh.cpp        | 13 +-----

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

diff --git a/src/add-ons/kernel/bus_managers/usb/Device.cpp 
b/src/add-ons/kernel/bus_managers/usb/Device.cpp
index f15b52216d..83e8adb509 100644
--- a/src/add-ons/kernel/bus_managers/usb/Device.cpp
+++ b/src/add-ons/kernel/bus_managers/usb/Device.cpp
@@ -254,6 +254,22 @@ Device::Device(Object* parent, int8 hubAddress, uint8 
hubPort,
                                        break;
                                }
 
+                               case USB_DESCRIPTOR_ENDPOINT_COMPANION: {
+                                       usb_endpoint_descriptor* desc = 
currentInterface
+                                               
->endpoint[currentInterface->endpoint_count - 1].descr;
+                                       if ((uint8*)desc != 
(&configData[descriptorStart
+                                                       - desc->length])) {
+                                               TRACE_ERROR("found endpoint 
companion descriptor not immediately "
+                                                       "following endpoint 
descriptor, ignoring!\n");
+                                               break;
+                                       }
+                                       // TODO: It'd be nicer if we could 
store the endpoint companion
+                                       // descriptor along with the endpoint 
descriptor, but as the
+                                       // interface struct is public API, that 
would be an ABI break.
+
+                                       // fall through
+                               }
+
                                default:
                                        TRACE("got generic descriptor\n");
                                        usb_generic_descriptor* 
genericDescriptor
@@ -472,6 +488,29 @@ Device::InitEndpoints(int32 interfaceIndex)
                        usb_endpoint_info* endpoint = 
&interfaceInfo->endpoint[i];
                        Pipe* pipe = NULL;
 
+                       usb_endpoint_companion_descriptor* comp_descr = NULL;
+                       if (fSpeed == USB_SPEED_SUPER) {
+                               // We should have a companion descriptor for 
this device.
+                               // Let's find it: it'll be the "i"th one.
+                               size_t k = 0;
+                               for (size_t j = 0; j < 
interfaceInfo->generic_count; j++) {
+                                       usb_descriptor* desc = 
interfaceInfo->generic[j];
+                                       if (desc->endpoint.descriptor_type
+                                                       != 
USB_DESCRIPTOR_ENDPOINT_COMPANION) {
+                                               continue;
+                                       }
+                                       if (k == i) {
+                                               comp_descr = 
(usb_endpoint_companion_descriptor*)desc;
+                                               break;
+                                       }
+                                       k++;
+                               }
+                               if (comp_descr == NULL) {
+                                       TRACE_ERROR("SuperSpeed device without 
an endpoint companion "
+                                               "descriptor!");
+                               }
+                       }
+
                        Pipe::pipeDirection direction = Pipe::Out;
                        if ((endpoint->descr->endpoint_address & 0x80) != 0)
                                direction = Pipe::In;
@@ -505,6 +544,10 @@ Device::InitEndpoints(int32 interfaceIndex)
                                endpoint->descr->endpoint_address & 0x0f,
                                fSpeed, direction, 
endpoint->descr->max_packet_size,
                                endpoint->descr->interval, fHubAddress, 
fHubPort);
+                       if (comp_descr != NULL) {
+                               pipe->InitSuperSpeed(comp_descr->max_burst,
+                                       comp_descr->bytes_per_interval);
+                       }
                        endpoint->handle = pipe->USBID();
                }
        }
diff --git a/src/add-ons/kernel/bus_managers/usb/Pipe.cpp 
b/src/add-ons/kernel/bus_managers/usb/Pipe.cpp
index 96525ac359..6d976639c8 100644
--- a/src/add-ons/kernel/bus_managers/usb/Pipe.cpp
+++ b/src/add-ons/kernel/bus_managers/usb/Pipe.cpp
@@ -40,10 +40,21 @@ Pipe::InitCommon(int8 deviceAddress, uint8 endpointAddress, 
usb_speed speed,
        fHubAddress = hubAddress;
        fHubPort = hubPort;
 
+       fMaxBurst = 0;
+       fBytesPerInterval = 0;
+
        GetBusManager()->NotifyPipeChange(this, USB_CHANGE_CREATED);
 }
 
 
+void
+Pipe::InitSuperSpeed(uint8 maxBurst, uint16 bytesPerInterval)
+{
+       fMaxBurst = maxBurst;
+       fBytesPerInterval = bytesPerInterval;
+}
+
+
 void
 Pipe::SetHubInfo(int8 address, uint8 port)
 {
diff --git a/src/add-ons/kernel/bus_managers/usb/usb_private.h 
b/src/add-ons/kernel/bus_managers/usb/usb_private.h
index 93279c0865..2862f2c7c9 100644
--- a/src/add-ons/kernel/bus_managers/usb/usb_private.h
+++ b/src/add-ons/kernel/bus_managers/usb/usb_private.h
@@ -297,6 +297,8 @@ virtual     void                                            
        InitCommon(int8 deviceAddress,
                                                                                
        size_t maxPacketSize,
                                                                                
        uint8 interval,
                                                                                
        int8 hubAddress, uint8 hubPort);
+virtual void                                                   
InitSuperSpeed(uint8 maxBurst,
+                                                                               
        uint16 bytesPerInterval);
 
 virtual        uint32                                                  Type() 
const { return USB_OBJECT_PIPE; }
 virtual        const char *                                    TypeName() 
const { return "pipe"; }
@@ -311,6 +313,12 @@ virtual    const char *                                    
TypeName() const { return "pipe"; }
                                                                                
        { return fMaxPacketSize; }
                uint8                                                   
Interval() const { return fInterval; }
 
+               // SuperSpeed-only parameters
+               uint8                                                   
MaxBurst() const
+                                                                               
        { return fMaxBurst; }
+               uint16                                                  
BytesPerInterval() const
+                                                                               
        { return fBytesPerInterval; }
+
                // Hub port being the one-based logical port number on the hub
                void                                                    
SetHubInfo(int8 address, uint8 port);
                int8                                                    
HubAddress() const
@@ -342,6 +350,8 @@ private:
                usb_speed                                               fSpeed;
                size_t                                                  
fMaxPacketSize;
                uint8                                                   
fInterval;
+               uint8                                                   
fMaxBurst;
+               uint16                                                  
fBytesPerInterval;
                int8                                                    
fHubAddress;
                uint8                                                   
fHubPort;
                bool                                                    
fDataToggle;
diff --git a/src/add-ons/kernel/bus_managers/usb/usbspec_private.h 
b/src/add-ons/kernel/bus_managers/usb/usbspec_private.h
index dc8d068419..0a2899a5ae 100644
--- a/src/add-ons/kernel/bus_managers/usb/usbspec_private.h
+++ b/src/add-ons/kernel/bus_managers/usb/usbspec_private.h
@@ -71,6 +71,17 @@ struct usb_hub_descriptor {
 #define USB_DESCRIPTOR_HUB 0x29
 
 
+struct usb_endpoint_companion_descriptor {
+       uint8   length;
+       uint8   descriptor_type;
+       uint8   max_burst;
+       uint8   attributes;
+       uint16  bytes_per_interval;
+} _PACKED;
+
+#define USB_DESCRIPTOR_ENDPOINT_COMPANION 0x30
+
+
 // USB Spec 1.1 page 273
 struct usb_port_status
 {
diff --git a/src/add-ons/kernel/busses/usb/xhci.cpp 
b/src/add-ons/kernel/busses/usb/xhci.cpp
index 89d075f501..7508fca44a 100644
--- a/src/add-ons/kernel/busses/usb/xhci.cpp
+++ b/src/add-ons/kernel/busses/usb/xhci.cpp
@@ -1395,7 +1395,7 @@ XHCI::AllocateDevice(Hub *parent, int8 hubAddress, uint8 
hubPort,
 
        // configure the Control endpoint 0
        if (ConfigureEndpoint(slot, 0, USB_OBJECT_CONTROL_PIPE, false,
-                       device->trb_addr, 0, maxPacketSize, speed) != B_OK) {
+                       device->trb_addr, 0, maxPacketSize, speed, 0, 0) != 
B_OK) {
                TRACE_ERROR("unable to configure default control endpoint\n");
                delete_area(device->input_ctx_area);
                delete_area(device->device_ctx_area);
@@ -1645,7 +1645,8 @@ XHCI::_InsertEndpointForPipe(Pipe *pipe)
 
                status_t status = ConfigureEndpoint(device->slot, id, 
pipe->Type(),
                        pipe->Direction() == Pipe::In, 
device->endpoints[id].trb_addr,
-                       pipe->Interval(), pipe->MaxPacketSize(), 
usbDevice->Speed());
+                       pipe->Interval(), pipe->MaxPacketSize(), 
usbDevice->Speed(),
+                       pipe->MaxBurst(), pipe->BytesPerInterval());
                if (status != B_OK) {
                        TRACE_ERROR("unable to configure endpoint\n");
                        return status;
@@ -1844,7 +1845,8 @@ XHCI::_UnlinkDescriptorForPipe(xhci_td *descriptor, 
xhci_endpoint *endpoint)
 
 status_t
 XHCI::ConfigureEndpoint(uint8 slot, uint8 number, uint8 type, bool directionIn,
-       uint64 ringAddr, uint16 interval, uint16 maxPacketSize, usb_speed speed)
+       uint64 ringAddr, uint16 interval, uint16 maxPacketSize, usb_speed speed,
+       uint8 maxBurst, uint16 bytesPerInterval)
 {
        struct xhci_device* device = &fDevices[slot];
 
@@ -1903,21 +1905,18 @@ XHCI::ConfigureEndpoint(uint8 slot, uint8 number, uint8 
type, bool directionIn,
 
        // For non-isochronous endpoints, we want the controller to retry failed
        // transfers, if possible. (XHCI 1.1 § 4.10.2.3 p189.)
-       if (!(type & USB_OBJECT_ISO_PIPE))
+       if ((type & USB_OBJECT_ISO_PIPE) == 0)
                dwendpoint1 |= ENDPOINT_1_CERR(3);
 
-       // Assign maximum burst size.
-       // TODO: While computing the maximum burst this way is correct for USB2
-       // devices, it is merely acceptable for USB3 devices, which have a more
-       // correct value stored in the Companion Descriptor. (Further, this 
value
-       // in the USB3 Companion Descriptor is to be used for *all* endpoints, 
not
-       // just Interrupt and Isoch ones.)
-       uint8 maxBurst = (maxPacketSize & 0x1800) >> 11;
-       if (speed >= USB_SPEED_HIGHSPEED
-                       && (((type & USB_OBJECT_INTERRUPT_PIPE) != 0)
-                               || (type & USB_OBJECT_ISO_PIPE) != 0)) {
-               dwendpoint1 |= ENDPOINT_1_MAXBURST(maxBurst);
+       // Assign maximum burst size. For USB3 devices this is passed in; for
+       // all other devices we compute it. (XHCI 1.1 § 4.8.2 p154.)
+       if (speed == USB_SPEED_HIGHSPEED && (type & (USB_OBJECT_INTERRUPT_PIPE
+                       | USB_OBJECT_ISO_PIPE)) != 0) {
+               maxBurst = (maxPacketSize & 0x1800) >> 11;
+       } else if (speed != USB_SPEED_SUPER) {
+               maxBurst = 0;
        }
+       dwendpoint1 |= ENDPOINT_1_MAXBURST(maxBurst);
 
        // Assign maximum packet size, set the ring address, and set the
        // "Dequeue Cycle State" bit. (XHCI 1.1 § 6.2.3 Table 6-10 p430.)
@@ -1934,10 +1933,15 @@ XHCI::ConfigureEndpoint(uint8 slot, uint8 number, uint8 
type, bool directionIn,
        }
 
        // Assign maximum ESIT payload. (XHCI 1.1 § 4.14.2 p250.)
-       // TODO: This computation is *only* correct for USB2 devices.
-       if (((type & USB_OBJECT_INTERRUPT_PIPE) != 0)
-                       || ((type & USB_OBJECT_ISO_PIPE) != 0)) {
-               dwendpoint4 |= ENDPOINT_4_MAXESITPAYLOAD((maxBurst + 1) * 
maxPacketSize);
+       if ((type & (USB_OBJECT_INTERRUPT_PIPE | USB_OBJECT_ISO_PIPE)) != 0) {
+               // TODO: For SuperSpeedPlus endpoints, there is yet another 
descriptor
+               // for isochronous endpoints that specifies the maximum ESIT 
payload.
+               // We don't fetch this yet, so just fall back to the USB2 
computation
+               // method if bytesPerInterval is 0.
+               if (speed == USB_SPEED_SUPER && bytesPerInterval != 0)
+                       dwendpoint4 |= 
ENDPOINT_4_MAXESITPAYLOAD(bytesPerInterval);
+               else if (speed >= USB_SPEED_HIGHSPEED)
+                       dwendpoint4 |= ENDPOINT_4_MAXESITPAYLOAD((maxBurst + 1) 
* maxPacketSize);
        }
 
        _WriteContext(&device->input_ctx->endpoints[number].dwendpoint0,
diff --git a/src/add-ons/kernel/busses/usb/xhci.h 
b/src/add-ons/kernel/busses/usb/xhci.h
index 674c421a3d..f5d5a07b9a 100644
--- a/src/add-ons/kernel/busses/usb/xhci.h
+++ b/src/add-ons/kernel/busses/usb/xhci.h
@@ -137,7 +137,8 @@ private:
                        status_t                        ConfigureEndpoint(uint8 
slot, uint8 number,
                                                                        uint8 
type, bool directionIn, uint64 ringAddr,
                                                                        uint16 
interval, uint16 maxPacketSize,
-                                                                       
usb_speed speed);
+                                                                       
usb_speed speed, uint8 maxBurst,
+                                                                       uint16 
bytesPerInterval);
                        status_t                        
_InsertEndpointForPipe(Pipe *pipe);
                        status_t                        
_RemoveEndpointForPipe(Pipe *pipe);
 
diff --git a/src/add-ons/kernel/busses/usb/xhci_rh.cpp 
b/src/add-ons/kernel/busses/usb/xhci_rh.cpp
index 5556c8c08c..e313b136ed 100644
--- a/src/add-ons/kernel/busses/usb/xhci_rh.cpp
+++ b/src/add-ons/kernel/busses/usb/xhci_rh.cpp
@@ -31,20 +31,11 @@ static usb_device_descriptor sXHCIRootHubDevice =
 };
 
 
-struct usb_endpoint_ss_comp_descriptor {
-       uint8   length;
-       uint8   descriptor_type;
-       uint16  burst;
-       uint8   attributes;
-       uint16  internal;
-} _PACKED;
-
-
 struct xhci_root_hub_configuration_s {
        usb_configuration_descriptor    configuration;
        usb_interface_descriptor                interface;
        usb_endpoint_descriptor                 endpoint;
-       usb_endpoint_ss_comp_descriptor endpc;
+       usb_endpoint_companion_descriptor endpc;
        usb_hub_descriptor                              hub;
 } _PACKED;
 
@@ -86,7 +77,7 @@ static xhci_root_hub_configuration_s sXHCIRootHubConfig =
 
        { // endpoint companion descriptor
                7,
-               0x30,
+               USB_DESCRIPTOR_ENDPOINT_COMPANION,
                0,
                0,
                0


Other related posts:

  • » [haiku-commits] haiku: hrev53137 - in src/add-ons/kernel: busses/usb bus_managers/usb - waddlesplash