Changeset e4dbfda in mainline for uspace/lib/usb/src/hcdhubd.c


Ignore:
Timestamp:
2010-11-26T21:26:15Z (13 years ago)
Author:
Vojtech Horky <vojtechhorky@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
08f747e
Parents:
172c1682
Message:

Bypassed deadlock in devman

It is possible to register hubs.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/usb/src/hcdhubd.c

    r172c1682 re4dbfda  
    263263int usb_hcd_add_root_hub(usb_hc_device_t *dev)
    264264{
     265        char *id;
     266        int rc = asprintf(&id, "usb&hc=%s&hub", dev->generic->name);
     267        if (rc <= 0) {
     268                return rc;
     269        }
     270
     271        rc = usb_hc_add_child_device(dev->generic, USB_HUB_DEVICE_NAME, id);
     272        if (rc != EOK) {
     273                free(id);
     274        }
     275
     276        return rc;
     277}
     278
     279/** Info about child device. */
     280struct child_device_info {
     281        device_t *parent;
     282        const char *name;
     283        const char *match_id;
     284};
     285
     286/** Adds a child device fibril worker. */
     287static int fibril_add_child_device(void *arg)
     288{
     289        struct child_device_info *child_info
     290            = (struct child_device_info *) arg;
    265291        int rc;
    266292
    267         /*
    268          * Announce presence of child device.
    269          */
    270         device_t *hub = NULL;
     293        device_t *child = create_device();
    271294        match_id_t *match_id = NULL;
    272295
    273         hub = create_device();
    274         if (hub == NULL) {
     296        if (child == NULL) {
    275297                rc = ENOMEM;
    276298                goto failure;
    277299        }
    278         hub->name = USB_HUB_DEVICE_NAME;
     300        child->name = child_info->name;
    279301
    280302        match_id = create_match_id();
     
    283305                goto failure;
    284306        }
    285 
    286         char *id;
    287         rc = asprintf(&id, "usb&hc=%s&hub", dev->generic->name);
    288         if (rc <= 0) {
    289                 rc = ENOMEM;
     307        match_id->id = child_info->match_id;
     308        match_id->score = 10;
     309        printf("adding child device with match \"%s\"\n", match_id->id);
     310        add_match_id(&child->match_ids, match_id);
     311
     312        rc = child_device_register(child, child_info->parent);
     313        if (rc != EOK) {
    290314                goto failure;
    291315        }
    292316
    293         match_id->id = id;
    294         match_id->score = 30;
    295 
    296         add_match_id(&hub->match_ids, match_id);
    297 
    298         rc = child_device_register(hub, dev->generic);
    299         if (rc != EOK) {
    300                 goto failure;
    301         }
    302 
    303         printf("%s: registered root hub\n", dev->generic->name);
     317        goto leave;
     318
     319failure:
     320        if (child != NULL) {
     321                child->name = NULL;
     322                delete_device(child);
     323        }
     324
     325        if (match_id != NULL) {
     326                match_id->id = NULL;
     327                delete_match_id(match_id);
     328        }
     329
     330leave:
     331        free(arg);
     332        return rc;
     333}
     334
     335/** Adds a child.
     336 * Due to deadlock in devman when parent registers child that oughts to be
     337 * driven by the same task, the child adding is done in separate fibril.
     338 * Not optimal, but it works.
     339 *
     340 * @param parent Parent device.
     341 * @param name Device name.
     342 * @param match_id Match id.
     343 * @return Error code.
     344 */
     345int usb_hc_add_child_device(device_t *parent, const char *name,
     346    const char *match_id)
     347{
     348        struct child_device_info *child_info
     349            = malloc(sizeof(struct child_device_info));
     350
     351        child_info->parent = parent;
     352        child_info->name = name;
     353        child_info->match_id = match_id;
     354
     355        fid_t fibril = fibril_create(fibril_add_child_device, child_info);
     356        if (!fibril) {
     357                return ENOMEM;
     358        }
     359        fibril_add_ready(fibril);
     360
    304361        return EOK;
    305 
    306 failure:
    307         if (hub != NULL) {
    308                 hub->name = NULL;
    309                 delete_device(hub);
    310         }
    311         delete_match_id(match_id);
    312 
    313         return rc;
    314362}
    315363
Note: See TracChangeset for help on using the changeset viewer.