Changeset 51a51be in mainline


Ignore:
Timestamp:
2018-01-16T21:19:37Z (6 years ago)
Author:
Ondřej Hlavatý <aearsis@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
1d218bf
Parents:
4603b35
Message:

usbhub: aggregate requests for default address

Location:
uspace/drv/bus/usb/usbhub
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/bus/usb/usbhub/port.c

    r4603b35 r51a51be  
    243243        }
    244244
    245         /* Reserve default address
    246          * TODO: Make the request synchronous.
    247          */
    248         while ((err = usbhc_reserve_default_address(exch)) == EAGAIN) {
    249                 fibril_condvar_wait_timeout(&port->state_cv, &port->guard, 500000);
    250                 if (port->state != PORT_CONNECTED) {
    251                         assert(port->state == PORT_ERROR);
    252                         port_change_state(port, PORT_DISABLED);
    253                         goto out_exch;
    254                 }
    255         }
     245        /* Reserve default address */
     246        err = usb_hub_reserve_default_address(port->hub, exch, &port->guard);
    256247        if (err != EOK) {
    257248                port_log(error, port, "Failed to reserve default address: %s", str_error(err));
     249                port_change_state(port, PORT_DISABLED);
     250                goto out_exch;
     251        }
     252
     253        /* Reservation of default address could have blocked */
     254        if (port->state != PORT_CONNECTED) {
     255                assert(port->state == PORT_ERROR);
     256                port_change_state(port, PORT_DISABLED);
    258257                goto out_exch;
    259258        }
     
    282281        if (port->state != PORT_ENABLED)
    283282                usb_hub_clear_port_feature(port->hub, port->port_number, USB_HUB_FEATURE_C_PORT_ENABLE);
    284 
    285283out_address:
    286         if ((err = usbhc_release_default_address(exch)))
    287                 port_log(error, port, "Failed to release default address: %s", str_error(err));
    288 
     284        usb_hub_release_default_address(port->hub, exch);
    289285out_exch:
    290286        usb_device_bus_exchange_end(exch);
    291 
    292287out:
    293288        assert(port->state == PORT_ENABLED || port->state == PORT_DISABLED);
  • uspace/drv/bus/usb/usbhub/usbhub.c

    r4603b35 r51a51be  
    116116        }
    117117        hub_dev->usb_device = usb_dev;
     118
     119        fibril_mutex_initialize(&hub_dev->default_address_guard);
     120        fibril_condvar_initialize(&hub_dev->default_address_cv);
    118121
    119122        /* Set hub's first configuration. (There should be only one) */
     
    603606
    604607/**
     608 * Reserve a default address for a port across all other devices connected to
     609 * the bus. We aggregate requests for ports to minimize delays between
     610 * connecting multiple devices from one hub - which happens e.g. when the hub
     611 * is connected with already attached devices.
     612 */
     613int usb_hub_reserve_default_address(usb_hub_dev_t *hub, async_exch_t *exch, fibril_mutex_t *guard)
     614{
     615        assert(hub);
     616        assert(exch);
     617        assert(guard);
     618        assert(fibril_mutex_is_locked(guard));
     619
     620        fibril_mutex_lock(&hub->default_address_guard);
     621        if (hub->default_address_requests++ == 0) {
     622                /* We're the first to request the address, we can just do it */
     623                fibril_mutex_unlock(&hub->default_address_guard);
     624                int err;
     625                while ((err = usbhc_reserve_default_address(exch)) == EAGAIN) {
     626                        fibril_mutex_unlock(guard);
     627                        async_usleep(500000);
     628                        fibril_mutex_lock(guard);
     629                        err = usbhc_reserve_default_address(exch);
     630                }
     631                return err;
     632        } else {
     633                /* Drop the port guard, we're going to wait */
     634                fibril_mutex_unlock(guard);
     635
     636                /* Wait for a signal */
     637                fibril_condvar_wait(&hub->default_address_cv, &hub->default_address_guard);
     638
     639                /* Remember ABBA, first drop the hub guard */
     640                fibril_mutex_unlock(&hub->default_address_guard);
     641                fibril_mutex_lock(guard);
     642                return EOK;
     643        }
     644}
     645
     646/**
     647 * Release the default address from a port.
     648 */
     649int usb_hub_release_default_address(usb_hub_dev_t *hub, async_exch_t *exch)
     650{
     651        fibril_mutex_lock(&hub->default_address_guard);
     652        if (--hub->default_address_requests == 0) {
     653                fibril_mutex_unlock(&hub->default_address_guard);
     654                return usbhc_release_default_address(exch);
     655        } else {
     656                fibril_condvar_signal(&hub->default_address_cv);
     657                fibril_mutex_unlock(&hub->default_address_guard);
     658                return EOK;
     659        }
     660}
     661
     662/**
    605663 * @}
    606664 */
  • uspace/drv/bus/usb/usbhub/usbhub.h

    r4603b35 r51a51be  
    7070        /** Each port is switched individually. */
    7171        bool per_port_power;
     72
     73        /** Default address management */
     74        unsigned default_address_requests;
     75        fibril_mutex_t default_address_guard;
     76        fibril_condvar_t default_address_cv;
    7277};
    7378
     
    8489bool hub_port_changes_callback(usb_device_t *, uint8_t *, size_t, void *);
    8590
     91int usb_hub_reserve_default_address(usb_hub_dev_t *, async_exch_t *, fibril_mutex_t *);
     92int usb_hub_release_default_address(usb_hub_dev_t *, async_exch_t *);
     93
    8694#endif
    8795
Note: See TracChangeset for help on using the changeset viewer.