VirtualBox

Changeset 93939 in vbox for trunk/src/VBox/Devices


Ignore:
Timestamp:
Feb 24, 2022 5:23:37 PM (3 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
150168
Message:

Devices/USB: Get rid of the address hashing mechanism and replace it with a lookup table approach, bugref:10196

Location:
trunk/src/VBox/Devices/USB
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/USB/DrvVUSBRootHub.cpp

    r93934 r93939  
    258258    pDev = pThis->apDevByPort[uPort];
    259259    if (RT_LIKELY(pDev))
    260         ASMAtomicIncU32(&pDev->cRefs);
     260        vusbDevRetain(pDev);
     261
     262    RTCritSectLeave(&pThis->CritSectDevices);
     263
     264    return pDev;
     265}
     266
     267
     268/**
     269 * Returns the attached VUSB device for the given port or NULL if none is attached.
     270 *
     271 * @returns Pointer to the VUSB device or NULL if not found.
     272 * @param   pThis               The VUSB roothub device instance.
     273 * @param   u8Address           The address to get the device for.
     274 *
     275 * @note The reference count of the VUSB device structure is retained to prevent it from going away.
     276 */
     277static PVUSBDEV vusbR3RhGetVUsbDevByAddrRetain(PVUSBROOTHUB pThis, uint8_t u8Address)
     278{
     279    PVUSBDEV pDev = NULL;
     280
     281    AssertReturn(u8Address < RT_ELEMENTS(pThis->apDevByAddr), NULL);
     282
     283    RTCritSectEnter(&pThis->CritSectDevices);
     284
     285    pDev = pThis->apDevByAddr[u8Address];
     286    if (RT_LIKELY(pDev))
     287        vusbDevRetain(pDev);
    261288
    262289    RTCritSectLeave(&pThis->CritSectDevices);
     
    353380
    354381/**
    355  * Finds an device attached to a roothub by it's address.
    356  *
    357  * @returns Pointer to the device.
    358  * @returns NULL if not found.
    359  * @param   pRh         Pointer to the root hub.
    360  * @param   Address     The device address.
    361  */
    362 static PVUSBDEV vusbRhFindDevByAddress(PVUSBROOTHUB pRh, uint8_t Address)
    363 {
    364     unsigned iHash = vusbHashAddress(Address);
    365     PVUSBDEV pDev = NULL;
    366 
    367     RTCritSectEnter(&pRh->CritSectDevices);
    368     for (PVUSBDEV pCur = pRh->apAddrHash[iHash]; pCur; pCur = pCur->pNextHash)
    369         if (pCur->u8Address == Address)
    370         {
    371             pDev = pCur;
    372             break;
    373         }
    374 
    375     if (pDev)
    376         vusbDevRetain(pDev);
    377     RTCritSectLeave(&pRh->CritSectDevices);
    378     return pDev;
    379 }
    380 
    381 
    382 /**
    383382 * Callback for freeing an URB.
    384383 * @param   pUrb    The URB to free.
     
    434433    PVUSBDEV pDev;
    435434    if (uPort == VUSB_DEVICE_PORT_INVALID)
    436         pDev = vusbRhFindDevByAddress(pRh, DstAddress);
     435        pDev = vusbR3RhGetVUsbDevByAddrRetain(pRh, DstAddress);
    437436    else
    438437        pDev = vusbR3RhGetVUsbDevByPortRetain(pRh, uPort);
     
    14491448    Assert(pDev->i16Port != -1);
    14501449
    1451     /*
    1452      * Check that it's attached and unlink it from the linked list.
    1453      */
     1450    /* Check that it's attached and remvoe it. */
    14541451    RTCritSectEnter(&pRh->CritSectDevices);
    14551452    Assert(pRh->apDevByPort[pDev->i16Port] == pDev);
    1456     pRh->apDevByPort[pDev->i16Port] = NULL;
     1453    pRh->apDevByPort[pDev->i16Port]   = NULL;
     1454
     1455    if (pDev->u8Address == VUSB_DEFAULT_ADDRESS)
     1456    {
     1457        AssertPtr(pRh->apDevByAddr[VUSB_DEFAULT_ADDRESS]);
     1458
     1459        if (pDev == pRh->apDevByAddr[VUSB_DEFAULT_ADDRESS])
     1460            pRh->apDevByAddr[VUSB_DEFAULT_ADDRESS] = pDev->pNextDefAddr;
     1461        else
     1462        {
     1463            /* Search the list for the device and remove it. */
     1464            PVUSBDEV pDevPrev = pRh->apDevByAddr[VUSB_DEFAULT_ADDRESS];
     1465
     1466            while (   pDevPrev
     1467                   && pDevPrev->pNextDefAddr != pDev)
     1468                pDevPrev = pDevPrev->pNextDefAddr;
     1469
     1470            AssertPtr(pDevPrev);
     1471            pDevPrev->pNextDefAddr = pDev->pNextDefAddr;
     1472        }
     1473
     1474        pDev->pNextDefAddr = NULL;
     1475    }
     1476    else
     1477    {
     1478        Assert(pRh->apDevByAddr[pDev->u8Address] == pDev);
     1479        pRh->apDevByAddr[pDev->u8Address] = NULL;
     1480    }
    14571481    RTCritSectLeave(&pRh->CritSectDevices);
    14581482
  • trunk/src/VBox/Devices/USB/VUSBDevice.cpp

    r93914 r93939  
    994994
    995995/**
    996  * Add a device to the address hash
    997  */
    998 static void vusbDevAddressHash(PVUSBDEV pDev)
    999 {
    1000     if (pDev->u8Address == VUSB_INVALID_ADDRESS)
    1001         return;
    1002     uint8_t u8Hash = vusbHashAddress(pDev->u8Address);
    1003     pDev->pNextHash = pDev->pHub->pRootHub->apAddrHash[u8Hash];
    1004     pDev->pHub->pRootHub->apAddrHash[u8Hash] = pDev;
    1005 }
    1006 
    1007 /**
    1008  * Remove a device from the address hash
    1009  */
    1010 static void vusbDevAddressUnHash(PVUSBDEV pDev)
    1011 {
    1012     if (pDev->u8Address == VUSB_INVALID_ADDRESS)
    1013         return;
    1014 
    1015     uint8_t u8Hash = vusbHashAddress(pDev->u8Address);
    1016     pDev->u8Address = VUSB_INVALID_ADDRESS;
    1017     pDev->u8NewAddress = VUSB_INVALID_ADDRESS;
    1018 
    1019     RTCritSectEnter(&pDev->pHub->pRootHub->CritSectDevices);
    1020     PVUSBDEV pCur = pDev->pHub->pRootHub->apAddrHash[u8Hash];
    1021     if (pCur == pDev)
    1022     {
    1023         /* special case, we're at the head */
    1024         pDev->pHub->pRootHub->apAddrHash[u8Hash] = pDev->pNextHash;
    1025         pDev->pNextHash = NULL;
    1026     }
    1027     else
    1028     {
    1029         /* search the list */
    1030         PVUSBDEV pPrev;
    1031         for (pPrev = pCur, pCur = pCur->pNextHash;
    1032              pCur;
    1033              pPrev = pCur, pCur = pCur->pNextHash)
    1034         {
    1035             if (pCur == pDev)
    1036             {
    1037                 pPrev->pNextHash = pCur->pNextHash;
    1038                 pDev->pNextHash = NULL;
    1039                 break;
    1040             }
    1041         }
    1042     }
    1043     RTCritSectLeave(&pDev->pHub->pRootHub->CritSectDevices);
    1044 }
    1045 
    1046 /**
    1047996 * Sets the address of a device.
    1048997 *
     
    10771026        return;
    10781027
     1028    /** @todo The following logic belongs to the roothub and should actually be in that file. */
    10791029    PVUSBROOTHUB pRh = vusbDevGetRh(pDev);
    10801030    AssertPtrReturnVoid(pRh);
     1031
     1032    RTCritSectEnter(&pRh->CritSectDevices);
     1033
     1034    /* Remove the device from the current address. */
    10811035    if (pDev->u8Address == VUSB_DEFAULT_ADDRESS)
    1082         pRh->pDefaultAddress = NULL;
    1083 
    1084     vusbDevAddressUnHash(pDev);
     1036    {
     1037        AssertPtr(pRh->apDevByAddr[VUSB_DEFAULT_ADDRESS]);
     1038
     1039        if (pDev == pRh->apDevByAddr[VUSB_DEFAULT_ADDRESS])
     1040            pRh->apDevByAddr[VUSB_DEFAULT_ADDRESS] = pDev->pNextDefAddr;
     1041        else
     1042        {
     1043            /* Search the list for the device and remove it. */
     1044            PVUSBDEV pDevPrev = pRh->apDevByAddr[VUSB_DEFAULT_ADDRESS];
     1045
     1046            while (   pDevPrev
     1047                   && pDevPrev->pNextDefAddr != pDev)
     1048                pDevPrev = pDevPrev->pNextDefAddr;
     1049
     1050            AssertPtr(pDevPrev);
     1051            pDevPrev->pNextDefAddr = pDev->pNextDefAddr;
     1052        }
     1053
     1054        pDev->pNextDefAddr = NULL;
     1055    }
     1056    else
     1057        pRh->apDevByAddr[pDev->u8Address] = NULL;
    10851058
    10861059    if (u8Address == VUSB_DEFAULT_ADDRESS)
    10871060    {
    1088         if (pRh->pDefaultAddress != NULL)
     1061        PVUSBDEV pDevDef = pRh->apDevByAddr[VUSB_DEFAULT_ADDRESS];
     1062
     1063        if (pDevDef)
    10891064        {
    1090             vusbDevAddressUnHash(pRh->pDefaultAddress);
    1091             vusbDevSetStateCmp(pRh->pDefaultAddress, VUSB_DEVICE_STATE_POWERED, VUSB_DEVICE_STATE_DEFAULT);
     1065            vusbDevSetStateCmp(pDevDef, VUSB_DEVICE_STATE_POWERED, VUSB_DEVICE_STATE_DEFAULT);
    10921066            Log(("2 DEFAULT ADDRS\n"));
    10931067        }
    10941068
    1095         pRh->pDefaultAddress = pDev;
     1069        pDev->pNextDefAddr = pDevDef;
     1070        pRh->apDevByAddr[VUSB_DEFAULT_ADDRESS] = pDev;
    10961071        vusbDevSetState(pDev, VUSB_DEVICE_STATE_DEFAULT);
    10971072    }
    10981073    else
     1074    {
     1075        Assert(!pRh->apDevByAddr[u8Address]);
     1076        pRh->apDevByAddr[u8Address] = pDev;
    10991077        vusbDevSetState(pDev, VUSB_DEVICE_STATE_ADDRESS);
     1078    }
     1079
     1080    RTCritSectLeave(&pRh->CritSectDevices);
    11001081
    11011082    pDev->u8Address = u8Address;
    1102     vusbDevAddressHash(pDev);
    11031083
    11041084    Log(("vusb: %p[%s]/%i: Assigned address %u\n",
     
    13271307
    13281308    vusbDevCancelAllUrbs(pDev, true);
    1329     vusbDevAddressUnHash(pDev);
    13301309
    13311310    PVUSBROOTHUB pRh = vusbDevGetRh(pDev);
    13321311    if (!pRh)
    13331312        AssertMsgFailedReturn(("Not attached!\n"), VERR_VUSB_DEVICE_NOT_ATTACHED);
    1334     if (pRh->pDefaultAddress == pDev)
    1335         pRh->pDefaultAddress = NULL;
    1336 
     1313
     1314    /* The roothub will remove the device from the address to device array. */
    13371315    pDev->pHub->pOps->pfnDetach(pDev->pHub, pDev);
    13381316    pDev->i16Port = -1;
     
    18421820    pDev->IDevice.pfnGetSpeed = vusbIDeviceGetSpeed;
    18431821    pDev->pUsbIns = pUsbIns;
    1844     pDev->pNext = NULL;
    1845     pDev->pNextHash = NULL;
     1822    pDev->pNextDefAddr = NULL;
    18461823    pDev->pHub = NULL;
    18471824    pDev->enmState = VUSB_DEVICE_STATE_DETACHED;
  • trunk/src/VBox/Devices/USB/VUSBInternal.h

    r93934 r93939  
    225225    /** Pointer to the PDM USB device instance. */
    226226    PPDMUSBINS          pUsbIns;
    227     /** Next device in the chain maintained by the roothub. */
    228     PVUSBDEV            pNext;
    229     /** Pointer to the next device with the same address hash. */
    230     PVUSBDEV            pNextHash;
     227    /** Next device in the chain of devices with the default address. */
     228    PVUSBDEV            pNextDefAddr;
    231229    /** Pointer to the hub this device is attached to. */
    232230    PVUSBHUB            pHub;
     
    380378typedef struct VUSBROOTHUBLOAD *PVUSBROOTHUBLOAD;
    381379
    382 /** The address hash table size. */
    383 #define VUSB_ADDR_HASHSZ    5
    384 
    385380/**
    386381 * The instance data of a root hub driver.
     
    395390     * @todo remove this? */
    396391    VUSBHUB                     Hub;
    397     /** Address hash table. */
    398     PVUSBDEV                    apAddrHash[VUSB_ADDR_HASHSZ];
    399     /** The default address. */
    400     PVUSBDEV                    pDefaultAddress;
    401 
    402392    /** Pointer to the driver instance. */
    403393    PPDMDRVINS                  pDrvIns;
     
    411401    /** Array of pointers to USB devices indexed by the port the device is on. */
    412402    PVUSBDEV                    apDevByPort[VUSB_DEVICES_MAX];
     403    /** Array of pointers to USB devices indexed by the address assigned. */
     404    PVUSBDEV                    apDevByAddr[VUSB_DEVICES_MAX];
    413405    /** Structure after a saved state load to re-attach devices. */
    414406    PVUSBROOTHUBLOAD            pLoad;
     
    644636
    645637
    646 
    647 
    648 /**
    649  * Addresses are between 0 and 127 inclusive
    650  */
    651 DECLINLINE(uint8_t) vusbHashAddress(uint8_t Address)
    652 {
    653     uint8_t u8Hash = Address;
    654     u8Hash ^= (Address >> 2);
    655     u8Hash ^= (Address >> 3);
    656     u8Hash %= VUSB_ADDR_HASHSZ;
    657     return u8Hash;
    658 }
    659 
    660 
    661638/**
    662639 * Gets the roothub of a device.
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette