Changeset a066122c in mainline


Ignore:
Timestamp:
2011-05-28T15:21:48Z (13 years ago)
Author:
Vojtech Horky <vojtechhorky@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
4166fb1, bd7acda
Parents:
48141f0 (diff), dd143621 (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:

Hub driver fixes

Namely more defensive locking and a indefinite seizure of default
address. See log of merged revisions for more details.

Location:
uspace/drv/usbhub
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/usbhub/ports.c

    r48141f0 ra066122c  
    202202
    203203        //close address
    204         if(hub->ports[port].attached_device.address >= 0){
    205                 /*uncomment this code to use it when DDF allows device removal
    206                 opResult = usb_hc_unregister_device(
    207                         &hub->connection,
    208                         hub->attached_devs[port].address);
    209                 if(opResult != EOK) {
    210                         dprintf(USB_LOG_LEVEL_WARNING, "could not release "
    211                                 "address of "
    212                             "removed device: %d", opResult);
    213                 }
    214                 hub->attached_devs[port].address = 0;
    215                 hub->attached_devs[port].handle = 0;
    216                  */
     204
     205        usb_hub_port_t *the_port = hub->ports + port;
     206
     207        fibril_mutex_lock(&hub->port_mutex);
     208
     209        if (the_port->attached_device.address >= 0) {
     210                usb_log_warning("Device unplug on `%s' (port %zu): " \
     211                    "not implemented.\n", hub->usb_device->ddf_dev->name,
     212                    (size_t) port);
     213                the_port->attached_device.address = -1;
     214                the_port->attached_device.handle = 0;
    217215        } else {
    218216                usb_log_warning("Device removed before being registered.\n");
     
    223221                 * port reset callback from new device wrapper.
    224222                 */
    225                 usb_hub_port_t *the_port = hub->ports + port;
    226223                fibril_mutex_lock(&the_port->reset_mutex);
    227224                the_port->reset_completed = true;
     
    230227                fibril_mutex_unlock(&the_port->reset_mutex);
    231228        }
     229
     230        fibril_mutex_unlock(&hub->port_mutex);
    232231}
    233232
     
    396395        }
    397396
     397        fibril_mutex_lock(&data->hub->port_mutex);
    398398        data->hub->ports[data->port].attached_device.handle = child_handle;
    399399        data->hub->ports[data->port].attached_device.address = new_address;
     400        fibril_mutex_unlock(&data->hub->port_mutex);
    400401
    401402        usb_log_info("Detected new device on `%s' (port %zu), "
     
    406407leave:
    407408        free(arg);
     409
     410        fibril_mutex_lock(&data->hub->pending_ops_mutex);
     411        assert(data->hub->pending_ops_count > 0);
     412        data->hub->pending_ops_count--;
     413        fibril_condvar_signal(&data->hub->pending_ops_cv);
     414        fibril_mutex_unlock(&data->hub->pending_ops_mutex);
     415
    408416
    409417        return EOK;
     
    452460                return ENOMEM;
    453461        }
     462        fibril_mutex_lock(&hub->pending_ops_mutex);
     463        hub->pending_ops_count++;
     464        fibril_mutex_unlock(&hub->pending_ops_mutex);
    454465        fibril_add_ready(fibril);
    455466
  • uspace/drv/usbhub/usbhub.c

    r48141f0 ra066122c  
    7272static void usb_hub_process_global_interrupt(usb_hub_info_t * hub_info);
    7373
    74 static void usb_hub_polling_terminted_callback(usb_device_t * device,
     74static void usb_hub_polling_terminated_callback(usb_device_t * device,
    7575    bool was_error, void * data);
    7676
     
    200200        result->control_pipe = &usb_dev->ctrl_pipe;
    201201        result->is_default_address_used = false;
     202
     203        result->ports = NULL;
     204        result->port_count = (size_t) -1;
     205        fibril_mutex_initialize(&result->port_mutex);
     206
     207        fibril_mutex_initialize(&result->pending_ops_mutex);
     208        fibril_condvar_initialize(&result->pending_ops_cv);
     209        result->pending_ops_count = 0;
    202210        return result;
    203211}
     
    340348        rc = usb_device_auto_poll(hub_info->usb_device, 0,
    341349            hub_port_changes_callback, ((hub_info->port_count + 1) / 8) + 1,
    342             usb_hub_polling_terminted_callback, hub_info);
     350            usb_hub_polling_terminated_callback, hub_info);
    343351        if (rc != EOK) {
    344352                usb_log_error("Failed to create polling fibril: %s.\n",
     
    473481 * @param data pointer to usb_hub_info_t structure
    474482 */
    475 static void usb_hub_polling_terminted_callback(usb_device_t * device,
     483static void usb_hub_polling_terminated_callback(usb_device_t * device,
    476484    bool was_error, void * data){
    477         usb_hub_info_t * hub_info = data;
    478         if(!hub_info) return;
    479         free(hub_info->ports);
    480         free(hub_info);
     485        usb_hub_info_t * hub = data;
     486        assert(hub);
     487
     488        fibril_mutex_lock(&hub->pending_ops_mutex);
     489
     490        /* The device is dead. However there might be some pending operations
     491         * that we need to wait for.
     492         * One of them is device adding in progress.
     493         * The respective fibril is probably waiting for status change
     494         * in port reset (port enable) callback.
     495         * Such change would never come (otherwise we would not be here).
     496         * Thus, we would flush all pending port resets.
     497         */
     498        if (hub->pending_ops_count > 0) {
     499                fibril_mutex_lock(&hub->port_mutex);
     500                size_t port;
     501                for (port = 0; port < hub->port_count; port++) {
     502                        usb_hub_port_t *the_port = hub->ports + port;
     503                        fibril_mutex_lock(&the_port->reset_mutex);
     504                        the_port->reset_completed = true;
     505                        the_port->reset_okay = false;
     506                        fibril_condvar_broadcast(&the_port->reset_cv);
     507                        fibril_mutex_unlock(&the_port->reset_mutex);
     508                }
     509                fibril_mutex_unlock(&hub->port_mutex);
     510        }
     511        /* And now wait for them. */
     512        while (hub->pending_ops_count > 0) {
     513                fibril_condvar_wait(&hub->pending_ops_cv,
     514                    &hub->pending_ops_mutex);
     515        }
     516        fibril_mutex_unlock(&hub->pending_ops_mutex);
     517
     518        free(hub->ports);
     519        free(hub);
    481520}
    482521
  • uspace/drv/usbhub/usbhub.h

    r48141f0 ra066122c  
    6161        usb_hub_port_t *ports;
    6262
     63        fibril_mutex_t port_mutex;
     64
    6365        /** connection to hcd */
    6466        usb_hc_connection_t connection;
     
    8991        /** generic usb device data*/
    9092        usb_device_t * usb_device;
     93
     94        /** Number of pending operations on the mutex to prevent shooting
     95         * ourselves in the foot.
     96         * When the hub is disconnected but we are in the middle of some
     97         * operation, we cannot destroy this structure right away because
     98         * the pending operation might use it.
     99         */
     100        size_t pending_ops_count;
     101        /** Guard for pending_ops_count. */
     102        fibril_mutex_t pending_ops_mutex;
     103        /** Condition variable for pending_ops_count. */
     104        fibril_condvar_t pending_ops_cv;
     105
    91106};
    92107
Note: See TracChangeset for help on using the changeset viewer.