Changeset 4f66cc7b in mainline for uspace/drv/uhci-hcd/transfer_list.c


Ignore:
Timestamp:
2011-03-17T12:45:23Z (14 years ago)
Author:
Lubos Slovak <lubos.slovak@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
4fec9ee, 6e3b9a58
Parents:
45dd8bf (diff), 039c66c (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:

Merged development changes

File:
1 edited

Legend:

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

    r45dd8bf r4f66cc7b  
    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
     
    4140    transfer_list_t *instance, batch_t *batch);
    4241/*----------------------------------------------------------------------------*/
    43 /** Initializes transfer list structures.
     42/** Initialize transfer list structures.
    4443 *
    4544 * @param[in] instance Memory place to use.
    46  * @param[in] name Name of te new list.
    47  * @return Error code
    48  *
    49  * Allocates memory for internat queue_head_t structure.
     45 * @param[in] name Name of the new list.
     46 * @return Error code
     47 *
     48 * Allocates memory for internal qh_t structure.
    5049 */
    5150int transfer_list_init(transfer_list_t *instance, const char *name)
    5251{
    5352        assert(instance);
    54         instance->next = NULL;
    5553        instance->name = name;
    56         instance->queue_head = malloc32(sizeof(queue_head_t));
     54        instance->queue_head = malloc32(sizeof(qh_t));
    5755        if (!instance->queue_head) {
    5856                usb_log_error("Failed to allocate queue head.\n");
     
    6159        instance->queue_head_pa = addr_to_phys(instance->queue_head);
    6260
    63         queue_head_init(instance->queue_head);
     61        qh_init(instance->queue_head);
    6462        list_initialize(&instance->batch_list);
    6563        fibril_mutex_initialize(&instance->guard);
     
    6765}
    6866/*----------------------------------------------------------------------------*/
    69 /** Set the next list in chain.
     67/** Set the next list in transfer list chain.
    7068 *
    7169 * @param[in] instance List to lead.
    7270 * @param[in] next List to append.
    7371 * @return Error code
     72 *
     73 * Does not check whether this replaces an existing list .
    7474 */
    7575void transfer_list_set_next(transfer_list_t *instance, transfer_list_t *next)
     
    7979        if (!instance->queue_head)
    8080                return;
    81         queue_head_append_qh(instance->queue_head, next->queue_head_pa);
    82         instance->queue_head->element = instance->queue_head->next_queue;
    83 }
    84 /*----------------------------------------------------------------------------*/
    85 /** Submits a new transfer batch to list and queue.
     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.
    8687 *
    8788 * @param[in] instance List to use.
    8889 * @param[in] batch Transfer batch to submit.
    8990 * @return Error code
     91 *
     92 * The batch is added to the end of the list and queue.
    9093 */
    9194void transfer_list_add_batch(transfer_list_t *instance, batch_t *batch)
     
    9396        assert(instance);
    9497        assert(batch);
    95         usb_log_debug2(
    96             "Adding batch(%p) to queue %s.\n", batch, instance->name);
    97 
    98         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);
    99101        assert((pa & LINK_POINTER_ADDRESS_MASK) == pa);
    100         pa |= LINK_POINTER_QUEUE_HEAD_FLAG;
    101 
    102         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);
    103106
    104107        fibril_mutex_lock(&instance->guard);
    105108
    106         if (instance->queue_head->element == instance->queue_head->next_queue) {
    107                 /* there is nothing scheduled */
    108                 list_append(&batch->link, &instance->batch_list);
    109                 instance->queue_head->element = pa;
    110                 usb_log_debug("Batch(%p) added to queue %s first.\n",
    111                         batch, instance->name);
    112                 fibril_mutex_unlock(&instance->guard);
    113                 return;
    114         }
    115         /* now we can be sure that there is someting scheduled */
    116         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
    117124        batch_t *first = list_get_instance(
    118                   instance->batch_list.next, batch_t, link);
    119         batch_t *last = list_get_instance(
    120             instance->batch_list.prev, batch_t, link);
    121         queue_head_append_qh(last->qh, pa);
    122         list_append(&batch->link, &instance->batch_list);
    123 
    124         usb_log_debug("Batch(%p) added to queue %s last, first is %p.\n",
     125            instance->batch_list.next, batch_t, link);
     126        usb_log_debug("Batch(%p) added to queue %s, first is %p.\n",
    125127                batch, instance->name, first);
    126128        fibril_mutex_unlock(&instance->guard);
    127129}
    128130/*----------------------------------------------------------------------------*/
    129 /** Removes a transfer batch from list and queue.
     131/** Remove a transfer batch from the list and queue.
    130132 *
    131133 * @param[in] instance List to use.
    132134 * @param[in] batch Transfer batch to remove.
    133135 * @return Error code
     136 *
     137 * Does not lock the transfer list, caller is responsible for that.
    134138 */
    135139void transfer_list_remove_batch(transfer_list_t *instance, batch_t *batch)
     
    140144        assert(batch->qh);
    141145        usb_log_debug2(
    142             "Removing batch(%p) from queue %s.\n", batch, instance->name);
    143 
     146            "Queue %s: removing batch(%p).\n", instance->name, batch);
     147
     148        const char * pos = NULL;
     149        /* Remove from the hardware queue */
    144150        if (batch->link.prev == &instance->batch_list) {
    145151                /* I'm the first one here */
    146                 usb_log_debug(
    147                     "Batch(%p) removed (FIRST) from %s, next element %x.\n",
    148                     batch, instance->name, batch->qh->next_queue);
    149                 instance->queue_head->element = batch->qh->next_queue;
     152                qh_set_element_qh(instance->queue_head, batch->qh->next);
     153                pos = "FIRST";
    150154        } else {
    151                 usb_log_debug(
    152                     "Batch(%p) removed (FIRST:NO) from %s, next element %x.\n",
    153                     batch, instance->name, batch->qh->next_queue);
    154155                batch_t *prev =
    155156                    list_get_instance(batch->link.prev, batch_t, link);
    156                 prev->qh->next_queue = batch->qh->next_queue;
    157         }
     157                qh_set_next_qh(prev->qh, batch->qh->next);
     158                pos = "NOT FIRST";
     159        }
     160        /* Remove from the driver list */
    158161        list_remove(&batch->link);
    159 }
    160 /*----------------------------------------------------------------------------*/
    161 /** Checks list for finished transfers.
     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.
    162167 *
    163168 * @param[in] instance List to use.
    164169 * @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.
    165174 */
    166175void transfer_list_remove_finished(transfer_list_t *instance)
     
    177186
    178187                if (batch_is_complete(batch)) {
     188                        /* Save for post-processing */
    179189                        transfer_list_remove_batch(instance, batch);
    180190                        list_append(current, &done);
Note: See TracChangeset for help on using the changeset viewer.