Changeset 0fd82c9 in mainline


Ignore:
Timestamp:
2011-03-17T13:49:41Z (13 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
1614ce3, 4fa05a32
Parents:
039c66c (diff), fcc525d (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:

HW error handling

minor fix in TD debug output

Location:
uspace/drv/uhci-hcd
Files:
7 edited

Legend:

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

    r039c66c r0fd82c9  
    153153}
    154154/*----------------------------------------------------------------------------*/
     155/** Mark batch as failed and continue with next step.
     156 *
     157 * @param[in] instance Batch structure to use.
     158 *
     159 */
     160void batch_abort(batch_t *instance)
     161{
     162        assert(instance);
     163        instance->error = EIO;
     164        instance->next_step(instance);
     165}
     166/*----------------------------------------------------------------------------*/
    155167/** Check batch TDs for activity.
    156168 *
     
    251263        assert(instance);
    252264        /* We are data out, we are supposed to provide data */
    253         memcpy(instance->transport_buffer, instance->buffer, instance->buffer_size);
     265        memcpy(instance->transport_buffer, instance->buffer,
     266            instance->buffer_size);
    254267        batch_data(instance, USB_PID_OUT);
    255268        instance->next_step = batch_call_out_and_dispose;
     
    281294        assert(instance);
    282295        /* We are data out, we are supposed to provide data */
    283         memcpy(instance->transport_buffer, instance->buffer, instance->buffer_size);
     296        memcpy(instance->transport_buffer, instance->buffer,
     297            instance->buffer_size);
    284298        batch_data(instance, USB_PID_OUT);
    285299        instance->next_step = batch_call_out_and_dispose;
  • uspace/drv/uhci-hcd/batch.h

    r039c66c r0fd82c9  
    6969} batch_t;
    7070
    71 batch_t * batch_get(ddf_fun_t *fun, usb_target_t target,
    72     usb_transfer_type_t transfer_type, size_t max_packet_size,
    73     usb_speed_t speed, char *buffer, size_t size,
    74                 char *setup_buffer, size_t setup_size,
     71batch_t * batch_get(
     72    ddf_fun_t *fun,
     73                usb_target_t target,
     74    usb_transfer_type_t transfer_type,
     75                size_t max_packet_size,
     76    usb_speed_t speed,
     77                char *buffer,
     78                size_t size,
     79                char *setup_buffer,
     80                size_t setup_size,
    7581    usbhc_iface_transfer_in_callback_t func_in,
    76     usbhc_iface_transfer_out_callback_t func_out, void *arg,
     82    usbhc_iface_transfer_out_callback_t func_out,
     83                void *arg,
    7784                device_keeper_t *manager
    7885                );
    7986
    8087void batch_dispose(batch_t *instance);
     88
     89void batch_abort(batch_t *instance);
    8190
    8291bool batch_is_complete(batch_t *instance);
  • uspace/drv/uhci-hcd/transfer_list.c

    r039c66c r0fd82c9  
    129129}
    130130/*----------------------------------------------------------------------------*/
     131/** Check list for finished batches.
     132 *
     133 * @param[in] instance List to use.
     134 * @return Error code
     135 *
     136 * Creates a local list of finished batches and calls next_step on each and
     137 * every one. This is safer because next_step may theoretically access
     138 * this transfer list leading to the deadlock if its done inline.
     139 */
     140void transfer_list_remove_finished(transfer_list_t *instance)
     141{
     142        assert(instance);
     143
     144        LIST_INITIALIZE(done);
     145
     146        fibril_mutex_lock(&instance->guard);
     147        link_t *current = instance->batch_list.next;
     148        while (current != &instance->batch_list) {
     149                link_t *next = current->next;
     150                batch_t *batch = list_get_instance(current, batch_t, link);
     151
     152                if (batch_is_complete(batch)) {
     153                        /* Save for post-processing */
     154                        transfer_list_remove_batch(instance, batch);
     155                        list_append(current, &done);
     156                }
     157                current = next;
     158        }
     159        fibril_mutex_unlock(&instance->guard);
     160
     161        while (!list_empty(&done)) {
     162                link_t *item = done.next;
     163                list_remove(item);
     164                batch_t *batch = list_get_instance(item, batch_t, link);
     165                batch->next_step(batch);
     166        }
     167}
     168/*----------------------------------------------------------------------------*/
     169/** Walk the list and abort all batches.
     170 *
     171 * @param[in] instance List to use.
     172 */
     173void transfer_list_abort_all(transfer_list_t *instance)
     174{
     175        fibril_mutex_lock(&instance->guard);
     176        while (list_empty(&instance->batch_list)) {
     177                link_t *current = instance->batch_list.next;
     178                batch_t *batch = list_get_instance(current, batch_t, link);
     179                transfer_list_remove_batch(instance, batch);
     180                batch_abort(batch);
     181        }
     182        fibril_mutex_unlock(&instance->guard);
     183}
     184/*----------------------------------------------------------------------------*/
    131185/** Remove a transfer batch from the list and queue.
    132186 *
     
    163217            batch, pos, instance->name, batch->qh->next);
    164218}
    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  */
    175 void transfer_list_remove_finished(transfer_list_t *instance)
    176 {
    177         assert(instance);
    178 
    179         LIST_INITIALIZE(done);
    180 
    181         fibril_mutex_lock(&instance->guard);
    182         link_t *current = instance->batch_list.next;
    183         while (current != &instance->batch_list) {
    184                 link_t *next = current->next;
    185                 batch_t *batch = list_get_instance(current, batch_t, link);
    186 
    187                 if (batch_is_complete(batch)) {
    188                         /* Save for post-processing */
    189                         transfer_list_remove_batch(instance, batch);
    190                         list_append(current, &done);
    191                 }
    192                 current = next;
    193         }
    194         fibril_mutex_unlock(&instance->guard);
    195 
    196         while (!list_empty(&done)) {
    197                 link_t *item = done.next;
    198                 list_remove(item);
    199                 batch_t *batch = list_get_instance(item, batch_t, link);
    200                 batch->next_step(batch);
    201         }
    202 }
    203219/**
    204220 * @}
  • uspace/drv/uhci-hcd/transfer_list.h

    r039c66c r0fd82c9  
    6666void transfer_list_set_next(transfer_list_t *instance, transfer_list_t *next);
    6767
     68void transfer_list_add_batch(transfer_list_t *instance, batch_t *batch);
     69
    6870void transfer_list_remove_finished(transfer_list_t *instance);
    6971
    70 void transfer_list_add_batch(transfer_list_t *instance, batch_t *batch);
     72void transfer_list_abort_all(transfer_list_t *instance);
    7173#endif
    7274/**
  • uspace/drv/uhci-hcd/uhci_hc.c

    r039c66c r0fd82c9  
    9797
    9898        instance->hw_interrupts = interrupts;
     99        instance->hw_failures = 0;
     100
    99101        /* Setup UHCI function. */
    100102        instance->ddf_instance = fun;
     
    149151        while ((pio_read_16(&registers->usbcmd) & UHCI_CMD_HCRESET) != 0);
    150152
    151         /* Set framelist pointer */
     153        /* Set frame to exactly 1ms */
     154        pio_write_8(&registers->sofmod, 64);
     155
     156        /* Set frame list pointer */
    152157        const uint32_t pa = addr_to_phys(instance->frame_list);
    153158        pio_write_32(&registers->flbaseadd, pa);
     
    347352{
    348353        assert(instance);
    349         /* TODO: Check interrupt cause here */
     354        /* TODO: Resume interrupts are not supported */
    350355        /* Lower 2 bits are transaction error and transaction complete */
    351356        if (status & 0x3) {
     
    354359                transfer_list_remove_finished(&instance->transfers_control_full);
    355360                transfer_list_remove_finished(&instance->transfers_bulk_full);
     361        }
     362        /* bits 4 and 5 indicate hc error */
     363        if (status & 0x18) {
     364                usb_log_error("UHCI hardware failure!.\n");
     365                ++instance->hw_failures;
     366                transfer_list_abort_all(&instance->transfers_interrupt);
     367                transfer_list_abort_all(&instance->transfers_control_slow);
     368                transfer_list_abort_all(&instance->transfers_control_full);
     369                transfer_list_abort_all(&instance->transfers_bulk_full);
     370
     371                if (instance->hw_failures < UHCI_ALLOWED_HW_FAIL) {
     372                        /* reinitialize hw, this triggers virtual disconnect*/
     373                        uhci_hc_init_hw(instance);
     374                } else {
     375                        usb_log_fatal("Too many UHCI hardware failures!.\n");
     376                        uhci_hc_fini(instance);
     377                }
    356378        }
    357379}
  • uspace/drv/uhci-hcd/uhci_hc.h

    r039c66c r0fd82c9  
    8080#define UHCI_CLEANER_TIMEOUT 10000
    8181#define UHCI_DEBUGER_TIMEOUT 5000000
     82#define UHCI_ALLOWED_HW_FAIL 5
    8283
    8384typedef struct uhci_hc {
     
    100101        fid_t debug_checker;
    101102        bool hw_interrupts;
     103        unsigned hw_failures;
    102104
    103105        ddf_fun_t *ddf_instance;
  • uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.c

    r039c66c r0fd82c9  
    159159            (s & TD_STATUS_ERROR_BIT_STUFF) ? " BIT_STUFF," : "",
    160160            (s & TD_STATUS_ERROR_RESERVED) ? " RESERVED," : "",
    161             (s >> TD_STATUS_ACTLEN_POS) & TD_STATUS_ACTLEN_MASK
     161            td_act_size(instance)
    162162        );
    163163}
Note: See TracChangeset for help on using the changeset viewer.