Changeset 72af8da in mainline for uspace/drv/uhci-hcd/transfer_list.c


Ignore:
Timestamp:
2011-03-16T18:50:17Z (14 years ago)
Author:
Matus Dekanek <smekideki@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
42a3a57
Parents:
3e7b7cd (diff), fcf07e6 (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:

merge from usb/development

File:
1 edited

Legend:

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

    r3e7b7cd r72af8da  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup usb
     28/** @addtogroup drvusbuhcihc
    2929 * @{
    3030 */
    3131/** @file
    32  * @brief UHCI driver
     32 * @brief UHCI driver transfer list implementation
    3333 */
    3434#include <errno.h>
    35 
    3635#include <usb/debug.h>
    3736
    3837#include "transfer_list.h"
    3938
     39static void transfer_list_remove_batch(
     40    transfer_list_t *instance, batch_t *batch);
     41/*----------------------------------------------------------------------------*/
     42/** Initialize transfer list structures.
     43 *
     44 * @param[in] instance Memory place to use.
     45 * @param[in] name Name of the new list.
     46 * @return Error code
     47 *
     48 * Allocates memory for internal qh_t structure.
     49 */
    4050int transfer_list_init(transfer_list_t *instance, const char *name)
    4151{
    4252        assert(instance);
    43         instance->next = NULL;
    4453        instance->name = name;
    45         instance->queue_head = queue_head_get();
     54        instance->queue_head = malloc32(sizeof(qh_t));
    4655        if (!instance->queue_head) {
    4756                usb_log_error("Failed to allocate queue head.\n");
    4857                return ENOMEM;
    4958        }
    50         instance->queue_head_pa = (uintptr_t)addr_to_phys(instance->queue_head);
    51 
    52         queue_head_init(instance->queue_head);
     59        instance->queue_head_pa = addr_to_phys(instance->queue_head);
     60
     61        qh_init(instance->queue_head);
    5362        list_initialize(&instance->batch_list);
    5463        fibril_mutex_initialize(&instance->guard);
     
    5665}
    5766/*----------------------------------------------------------------------------*/
     67/** Set the next list in transfer list chain.
     68 *
     69 * @param[in] instance List to lead.
     70 * @param[in] next List to append.
     71 * @return Error code
     72 *
     73 * Does not check whether this replaces an existing list .
     74 */
    5875void transfer_list_set_next(transfer_list_t *instance, transfer_list_t *next)
    5976{
     
    6279        if (!instance->queue_head)
    6380                return;
    64         queue_head_append_qh(instance->queue_head, next->queue_head_pa);
    65         instance->queue_head->element = instance->queue_head->next_queue;
    66 }
    67 /*----------------------------------------------------------------------------*/
     81        /* Set both next and element to point to the same QH */
     82        qh_set_next_qh(instance->queue_head, next->queue_head_pa);
     83        qh_set_element_qh(instance->queue_head, next->queue_head_pa);
     84}
     85/*----------------------------------------------------------------------------*/
     86/** Submit transfer batch to the list and queue.
     87 *
     88 * @param[in] instance List to use.
     89 * @param[in] batch Transfer batch to submit.
     90 * @return Error code
     91 *
     92 * The batch is added to the end of the list and queue.
     93 */
    6894void transfer_list_add_batch(transfer_list_t *instance, batch_t *batch)
    6995{
    7096        assert(instance);
    7197        assert(batch);
    72         usb_log_debug2("Adding batch(%p) to queue %s.\n", batch, instance->name);
    73 
    74         uint32_t pa = (uintptr_t)addr_to_phys(batch->qh);
     98        usb_log_debug2("Queue %s: Adding batch(%p).\n", instance->name, batch);
     99
     100        const uint32_t pa = addr_to_phys(batch->qh);
    75101        assert((pa & LINK_POINTER_ADDRESS_MASK) == pa);
    76         pa |= LINK_POINTER_QUEUE_HEAD_FLAG;
    77 
    78         batch->qh->next_queue = instance->queue_head->next_queue;
     102
     103        /* New batch will be added to the end of the current list
     104         * so set the link accordingly */
     105        qh_set_next_qh(batch->qh, instance->queue_head->next);
    79106
    80107        fibril_mutex_lock(&instance->guard);
    81108
    82         if (instance->queue_head->element == instance->queue_head->next_queue) {
    83                 /* there is nothing scheduled */
    84                 list_append(&batch->link, &instance->batch_list);
    85                 instance->queue_head->element = pa;
    86                 usb_log_debug("Batch(%p) added to queue %s first.\n",
    87                         batch, instance->name);
    88                 fibril_mutex_unlock(&instance->guard);
    89                 return;
    90         }
    91         /* now we can be sure that there is someting scheduled */
    92         assert(!list_empty(&instance->batch_list));
     109        /* Add to the hardware queue. */
     110        if (list_empty(&instance->batch_list)) {
     111                /* There is nothing scheduled */
     112                qh_t *qh = instance->queue_head;
     113                assert(qh->element == qh->next);
     114                qh_set_element_qh(qh, pa);
     115        } else {
     116                /* There is something scheduled */
     117                batch_t *last = list_get_instance(
     118                    instance->batch_list.prev, batch_t, link);
     119                qh_set_next_qh(last->qh, pa);
     120        }
     121        /* Add to the driver list */
     122        list_append(&batch->link, &instance->batch_list);
     123
    93124        batch_t *first = list_get_instance(
    94                   instance->batch_list.next, batch_t, link);
    95         batch_t *last = list_get_instance(
    96             instance->batch_list.prev, batch_t, link);
    97         queue_head_append_qh(last->qh, pa);
    98         list_append(&batch->link, &instance->batch_list);
    99         usb_log_debug("Batch(%p) added to queue %s last, first is %p.\n",
    100                 batch, instance->name, first );
     125            instance->batch_list.next, batch_t, link);
     126        usb_log_debug("Batch(%p) added to queue %s, first is %p.\n",
     127                batch, instance->name, first);
    101128        fibril_mutex_unlock(&instance->guard);
    102129}
    103130/*----------------------------------------------------------------------------*/
    104 static void transfer_list_remove_batch(
    105     transfer_list_t *instance, batch_t *batch)
     131/** Remove a transfer batch from the list and queue.
     132 *
     133 * @param[in] instance List to use.
     134 * @param[in] batch Transfer batch to remove.
     135 * @return Error code
     136 *
     137 * Does not lock the transfer list, caller is responsible for that.
     138 */
     139void transfer_list_remove_batch(transfer_list_t *instance, batch_t *batch)
    106140{
    107141        assert(instance);
     
    109143        assert(instance->queue_head);
    110144        assert(batch->qh);
    111         usb_log_debug2("Removing batch(%p) from queue %s.\n", batch, instance->name);
    112 
    113         /* I'm the first one here */
     145        usb_log_debug2(
     146            "Queue %s: removing batch(%p).\n", instance->name, batch);
     147
     148        const char * pos = NULL;
     149        /* Remove from the hardware queue */
    114150        if (batch->link.prev == &instance->batch_list) {
    115                 usb_log_debug("Batch(%p) removed (FIRST) from queue %s, next element %x.\n",
    116                         batch, instance->name, batch->qh->next_queue);
    117                 instance->queue_head->element = batch->qh->next_queue;
     151                /* I'm the first one here */
     152                qh_set_element_qh(instance->queue_head, batch->qh->next);
     153                pos = "FIRST";
    118154        } else {
    119                 usb_log_debug("Batch(%p) removed (NOT FIRST) from queue, next element %x.\n",
    120                         batch, instance->name, batch->qh->next_queue);
    121                 batch_t *prev = list_get_instance(batch->link.prev, batch_t, link);
    122                 prev->qh->next_queue = batch->qh->next_queue;
    123         }
     155                batch_t *prev =
     156                    list_get_instance(batch->link.prev, batch_t, link);
     157                qh_set_next_qh(prev->qh, batch->qh->next);
     158                pos = "NOT FIRST";
     159        }
     160        /* Remove from the driver list */
    124161        list_remove(&batch->link);
    125 }
    126 /*----------------------------------------------------------------------------*/
     162        usb_log_debug("Batch(%p) removed (%s) from %s, next element %x.\n",
     163            batch, pos, instance->name, batch->qh->next);
     164}
     165/*----------------------------------------------------------------------------*/
     166/** Check list for finished batches.
     167 *
     168 * @param[in] instance List to use.
     169 * @return Error code
     170 *
     171 * Creates a local list of finished batches and calls next_step on each and
     172 * every one. This is safer because next_step may theoretically access
     173 * this transfer list leading to the deadlock if its done inline.
     174 */
    127175void transfer_list_remove_finished(transfer_list_t *instance)
    128176{
     
    138186
    139187                if (batch_is_complete(batch)) {
     188                        /* Save for post-processing */
    140189                        transfer_list_remove_batch(instance, batch);
    141190                        list_append(current, &done);
Note: See TracChangeset for help on using the changeset viewer.