Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset 5dfb70c9 in mainline


Ignore:
Timestamp:
2017-12-29T12:10:56Z (4 years ago)
Author:
Petr Manek <petr.manek@…>
Branches:
lfn, master
Children:
5c75456
Parents:
415c5116
Message:

uhci: moved offline call from usbhost, terminating hanging transfers

Location:
uspace
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/bus/usb/uhci/hc.c

    r415c5116 r5dfb70c9  
    321321}
    322322
     323static int device_online(device_t *device)
     324{
     325        // FIXME: Implement me!
     326
     327        return ENOTSUP;
     328}
     329
     330static int device_offline(device_t *device)
     331{
     332        hc_t *instance = bus_to_hc(device->bus);
     333        assert(instance);
     334
     335        int err;
     336        /* Tear down all drivers working with the device. */
     337        if ((err = ddf_fun_offline(device->fun))) {
     338                return err;
     339        }
     340
     341        /* At this point, all drivers are assumed to have already terminated
     342         * in a consistent way. The following code just cleans up hanging
     343         * transfers if there are any. */
     344
     345        /* Block creation of new endpoints and transfers. */
     346        usb_log_info("Device(%d): Going offline.", device->address);
     347        fibril_mutex_lock(&device->guard);
     348        device->online = false;
     349        fibril_mutex_unlock(&device->guard);
     350
     351        /* Abort all transfers to all endpoints. */
     352        transfer_list_abort_device(&instance->transfers_interrupt, device->address);
     353        transfer_list_abort_device(&instance->transfers_control_slow, device->address);
     354        transfer_list_abort_device(&instance->transfers_control_full, device->address);
     355        transfer_list_abort_device(&instance->transfers_bulk_full, device->address);
     356
     357        return EOK;
     358}
     359
    323360static int hc_status(bus_t *, uint32_t *);
    324361static int hc_schedule(usb_transfer_batch_t *);
     
    334371        .batch_schedule = hc_schedule,
    335372        .batch_destroy = destroy_transfer_batch,
     373
     374        .device_online = device_online,
     375        .device_offline = device_offline,
    336376};
    337377
  • uspace/drv/bus/usb/uhci/transfer_list.c

    r415c5116 r5dfb70c9  
    202202}
    203203
     204/** Walk the list and finish all batches of a specified device with EINTR.
     205 *
     206 * @param[in] instance List to use.
     207 * @param[in] address Address of the specified device. Other addresses are skipped.
     208 */
     209void transfer_list_abort_device(transfer_list_t *instance, usb_address_t address)
     210{
     211        fibril_mutex_lock(&instance->guard);
     212        link_t *current = list_first(&instance->batch_list);
     213        while (current && current != &instance->batch_list.head && !list_empty(&instance->batch_list)) {
     214                link_t * const next = current->next;
     215                uhci_transfer_batch_t *batch =
     216                    uhci_transfer_batch_from_link(current);
     217
     218                if (batch->base.target.address == address) {
     219                        transfer_list_remove_batch(instance, batch);
     220                        endpoint_abort(batch->base.ep);
     221                }
     222
     223                current = next;
     224        }
     225        fibril_mutex_unlock(&instance->guard);
     226}
     227
    204228/** Remove a transfer batch from the list and queue.
    205229 *
  • uspace/drv/bus/usb/uhci/transfer_list.h

    r415c5116 r5dfb70c9  
    6363void transfer_list_remove_finished(transfer_list_t *instance, list_t *done);
    6464void transfer_list_abort_all(transfer_list_t *instance);
     65void transfer_list_abort_device(transfer_list_t *instance, usb_address_t address);
    6566
    6667#endif
  • uspace/lib/usbhost/src/usb2_bus.c

    r415c5116 r5dfb70c9  
    352352}
    353353
    354 static int usb2_bus_device_online(device_t *device)
    355 {
    356         usb2_bus_t *bus = bus_to_usb2_bus(device->bus);
    357         assert(bus);
    358 
    359         // FIXME: Implement me!
    360 
    361         return ENOTSUP;
    362 }
    363 
    364 static int usb2_bus_device_offline(device_t *device)
    365 {
    366         usb2_bus_t *bus = bus_to_usb2_bus(device->bus);
    367         assert(bus);
    368 
    369         int err;
    370         /* Tear down all drivers working with the device. */
    371         if ((err = ddf_fun_offline(device->fun))) {
    372                 return err;
    373         }
    374 
    375         /* Block creation of new endpoints and transfers. */
    376         usb_log_info("Device(%d): Going offline.", device->address);
    377         fibril_mutex_lock(&device->guard);
    378         device->online = false;
    379         fibril_mutex_unlock(&device->guard);
    380 
    381         /* FIXME: This implementation leaves sleeping parts of drivers around.
    382          * With XHCI bus, the HID driver disengages and completely deactivates
    383          * when the DDF function is offlined. In USB2 bus, the driver receives
    384          * dev_remove and disengages "on paper" but later when interrupt message arrives,
    385          * some sleeping code is woken up and crashes the driver.
    386          *
    387          * The XHCI does 2 extra things that might prevent this behavior:
    388          *   (1) deconfigure the device,
    389          *   (2) deallocate all transfer TRB rings
    390          */
    391 
    392         return EOK;
    393 }
    394 
    395354static endpoint_t *usb2_bus_create_ep(device_t *dev, const usb_endpoint_desc_t *desc)
    396355{
     
    496455        .device_enumerate = usb2_bus_device_enumerate,
    497456        .device_find_endpoint = usb2_bus_find_ep,
    498         .device_online = usb2_bus_device_online,
    499         .device_offline = usb2_bus_device_offline,
    500457        .endpoint_create = usb2_bus_create_ep,
    501458        .endpoint_register = usb2_bus_register_ep,
Note: See TracChangeset for help on using the changeset viewer.