Changeset 5542b83 in mainline


Ignore:
Timestamp:
2011-04-02T15:47:45Z (13 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
322a8066, d8987b1
Parents:
969585f (diff), 0053fa38 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Add USB bandwidth control mechanism

Use per endpoint control transfer mutex
Bandwidth control issues warnings, drivers(libusb pipe init?) need to use it first.

Location:
uspace
Files:
2 added
8 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/uhci-hcd/hc.c

    r969585f r5542b83  
    239239        usb_log_debug("Initialized device manager.\n");
    240240
     241        ret = bandwidth_init(&instance->bandwidth, BANDWIDTH_AVAILABLE_USB11,
     242            bandwidth_count_usb11);
     243        assert(ret == true);
     244
    241245        return EOK;
    242246#undef CHECK_RET_DEST_CMDS_RETURN
     
    325329        if (!usb_is_allowed(
    326330            low_speed, batch->transfer_type, batch->max_packet_size)) {
    327                 usb_log_warning(
    328                     "Invalid USB transfer specified %s SPEED %d %zu.\n",
    329                     low_speed ? "LOW" : "FULL" , batch->transfer_type,
     331                usb_log_error("Invalid USB transfer specified %s %d %zu.\n",
     332                    usb_str_speed(batch->speed), batch->transfer_type,
    330333                    batch->max_packet_size);
    331334                return ENOTSUP;
    332335        }
    333         /* TODO: check available bandwidth here */
     336        /* Check available bandwidth */
     337        if (batch->transfer_type == USB_TRANSFER_INTERRUPT ||
     338            batch->transfer_type == USB_TRANSFER_ISOCHRONOUS) {
     339                int ret =
     340                    bandwidth_use(&instance->bandwidth, batch->target.address,
     341                    batch->target.endpoint, batch->direction);
     342                if (ret != EOK) {
     343                        usb_log_warning("Failed(%d) to use reserved bw: %s.\n",
     344                            ret, str_error(ret));
     345                }
     346        }
    334347
    335348        transfer_list_t *list =
     
    338351        if (batch->transfer_type == USB_TRANSFER_CONTROL) {
    339352                usb_device_keeper_use_control(
    340                     &instance->manager, batch->target.address);
     353                    &instance->manager, batch->target);
    341354        }
    342355        transfer_list_add_batch(list, batch);
     
    358371{
    359372        assert(instance);
     373//      status |= 1; //Uncomment to work around qemu hang
    360374        /* TODO: Resume interrupts are not supported */
    361375        /* Lower 2 bits are transaction error and transaction complete */
     
    376390                        usb_transfer_batch_t *batch =
    377391                            list_get_instance(item, usb_transfer_batch_t, link);
    378                         if (batch->transfer_type == USB_TRANSFER_CONTROL) {
     392                        switch (batch->transfer_type)
     393                        {
     394                        case USB_TRANSFER_CONTROL:
    379395                                usb_device_keeper_release_control(
    380                                     &instance->manager, batch->target.address);
     396                                    &instance->manager, batch->target);
     397                                break;
     398                        case USB_TRANSFER_INTERRUPT:
     399                        case USB_TRANSFER_ISOCHRONOUS: {
     400                                int ret = bandwidth_free(&instance->bandwidth,
     401                                    batch->target.address,
     402                                    batch->target.endpoint,
     403                                    batch->direction);
     404                                if (ret != EOK)
     405                                        usb_log_warning("Failed(%d) to free "
     406                                            "reserved bw: %s.\n", ret,
     407                                            str_error(ret));
     408                                }
     409                        default:
     410                                break;
    381411                        }
    382412                        batch->next_step(batch);
  • uspace/drv/uhci-hcd/hc.h

    r969585f r5542b83  
    4343#include <usbhc_iface.h>
    4444#include <usb/host/device_keeper.h>
     45#include <usb/host/bandwidth.h>
    4546
    4647#include "batch.h"
     
    8485typedef struct hc {
    8586        usb_device_keeper_t manager;
     87        bandwidth_t bandwidth;
    8688
    8789        regs_t *registers;
  • uspace/drv/uhci-hcd/iface.c

    r969585f r5542b83  
    128128}
    129129/*----------------------------------------------------------------------------*/
     130static int register_endpoint(
     131    ddf_fun_t *fun, usb_address_t address, usb_endpoint_t endpoint,
     132    usb_transfer_type_t transfer_type, usb_direction_t direction,
     133    size_t max_packet_size, unsigned int interval)
     134{
     135        hc_t *hc = fun_to_hc(fun);
     136        assert(hc);
     137        const usb_speed_t speed =
     138            usb_device_keeper_get_speed(&hc->manager, address);
     139        size_t size = max_packet_size;
     140
     141        usb_log_debug("Register endpoint %d:%d %s %s(%d) %zu(%zu) %u.\n",
     142            address, endpoint, usb_str_transfer_type(transfer_type),
     143            usb_str_speed(speed), direction, size, max_packet_size, interval);
     144        return bandwidth_reserve(&hc->bandwidth, address, endpoint, direction,
     145            speed, transfer_type, max_packet_size, size, interval);
     146}
     147/*----------------------------------------------------------------------------*/
     148static int unregister_endpoint(
     149    ddf_fun_t *fun, usb_address_t address,
     150    usb_endpoint_t endpoint, usb_direction_t direction)
     151{
     152        hc_t *hc = fun_to_hc(fun);
     153        assert(hc);
     154        usb_log_debug("Unregister endpoint %d:%d %d.\n",
     155            address, endpoint, direction);
     156        return bandwidth_release(&hc->bandwidth, address, endpoint, direction);
     157}
     158/*----------------------------------------------------------------------------*/
    130159/** Interrupt out transaction interface function
    131160 *
     
    365394        .release_address = release_address,
    366395
     396        .register_endpoint = register_endpoint,
     397        .unregister_endpoint = unregister_endpoint,
     398
    367399        .interrupt_out = interrupt_out,
    368400        .interrupt_in = interrupt_in,
  • uspace/lib/c/generic/adt/hash_table.c

    r969585f r5542b83  
    5454 *
    5555 */
    56 int hash_table_create(hash_table_t *h, hash_count_t m, hash_count_t max_keys,
     56bool hash_table_create(hash_table_t *h, hash_count_t m, hash_count_t max_keys,
    5757    hash_table_operations_t *op)
    5858{
  • uspace/lib/c/include/adt/hash_table.h

    r969585f r5542b83  
    3838#include <adt/list.h>
    3939#include <unistd.h>
     40#include <bool.h>
    4041
    4142typedef unsigned long hash_count_t;
     
    8384    list_get_instance((item), type, member)
    8485
    85 extern int hash_table_create(hash_table_t *, hash_count_t, hash_count_t,
     86extern bool hash_table_create(hash_table_t *, hash_count_t, hash_count_t,
    8687    hash_table_operations_t *);
    8788extern void hash_table_insert(hash_table_t *, unsigned long [], link_t *);
  • uspace/lib/usb/Makefile

    r969585f r5542b83  
    5353        src/hidreport.c \
    5454        src/host/device_keeper.c \
    55         src/host/batch.c
     55        src/host/batch.c \
     56        src/host/bandwidth.c
    5657
    5758include $(USPACE_PREFIX)/Makefile.common
  • uspace/lib/usb/include/usb/host/device_keeper.h

    r969585f r5542b83  
    5151        usb_speed_t speed;
    5252        bool occupied;
    53         bool control_used;
     53        uint16_t control_used;
    5454        uint16_t toggle_status[2];
    5555        devman_handle_t handle;
     
    9999
    100100void usb_device_keeper_use_control(usb_device_keeper_t *instance,
    101     usb_address_t address);
     101    usb_target_t target);
    102102
    103103void usb_device_keeper_release_control(usb_device_keeper_t *instance,
    104     usb_address_t address);
     104    usb_target_t target);
    105105
    106106#endif
  • uspace/lib/usb/src/host/device_keeper.c

    r969585f r5542b83  
    5454        for (; i < USB_ADDRESS_COUNT; ++i) {
    5555                instance->devices[i].occupied = false;
    56                 instance->devices[i].control_used = false;
     56                instance->devices[i].control_used = 0;
    5757                instance->devices[i].handle = 0;
    5858                instance->devices[i].toggle_status[0] = 0;
     
    311311/*----------------------------------------------------------------------------*/
    312312void usb_device_keeper_use_control(usb_device_keeper_t *instance,
    313     usb_address_t address)
    314 {
    315         assert(instance);
    316         fibril_mutex_lock(&instance->guard);
    317         while (instance->devices[address].control_used) {
     313    usb_target_t target)
     314{
     315        assert(instance);
     316        const uint16_t ep = 1 << target.endpoint;
     317        fibril_mutex_lock(&instance->guard);
     318        while (instance->devices[target.address].control_used & ep) {
    318319                fibril_condvar_wait(&instance->change, &instance->guard);
    319320        }
    320         instance->devices[address].control_used = true;
     321        instance->devices[target.address].control_used |= ep;
    321322        fibril_mutex_unlock(&instance->guard);
    322323}
    323324/*----------------------------------------------------------------------------*/
    324325void usb_device_keeper_release_control(usb_device_keeper_t *instance,
    325     usb_address_t address)
    326 {
    327         assert(instance);
    328         fibril_mutex_lock(&instance->guard);
    329         instance->devices[address].control_used = false;
     326    usb_target_t target)
     327{
     328        assert(instance);
     329        const uint16_t ep = 1 << target.endpoint;
     330        fibril_mutex_lock(&instance->guard);
     331        assert((instance->devices[target.address].control_used & ep) != 0);
     332        instance->devices[target.address].control_used &= ~ep;
    330333        fibril_mutex_unlock(&instance->guard);
    331334        fibril_condvar_signal(&instance->change);
Note: See TracChangeset for help on using the changeset viewer.