Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/devman/devman.c

    r7e752b2 r01b87dc5  
    6262}
    6363
     64static int devmap_devices_class_compare(unsigned long key[], hash_count_t keys,
     65    link_t *item)
     66{
     67        dev_class_info_t *class_info
     68            = hash_table_get_instance(item, dev_class_info_t, devmap_link);
     69        assert(class_info != NULL);
     70
     71        return (class_info->devmap_handle == (devmap_handle_t) key[0]);
     72}
     73
    6474static void devices_remove_callback(link_t *item)
    6575{
     
    7585        .hash = devices_hash,
    7686        .compare = devmap_devices_compare,
     87        .remove_callback = devices_remove_callback
     88};
     89
     90static hash_table_operations_t devmap_devices_class_ops = {
     91        .hash = devices_hash,
     92        .compare = devmap_devices_class_compare,
    7793        .remove_callback = devices_remove_callback
    7894};
     
    368384        printf(NAME ": create_root_node\n");
    369385
     386        fibril_rwlock_write_lock(&tree->rwlock);
    370387        node = create_dev_node();
    371388        if (node != NULL) {
     
    377394                tree->root_node = node;
    378395        }
     396        fibril_rwlock_write_unlock(&tree->rwlock);
    379397
    380398        return node != NULL;
     
    439457/** Start a driver
    440458 *
    441  * The driver's mutex is assumed to be locked.
    442  *
    443459 * @param drv           The driver's structure.
    444460 * @return              True if the driver's task is successfully spawned, false
     
    449465        int rc;
    450466
     467        assert(fibril_mutex_is_locked(&drv->driver_mutex));
     468       
    451469        printf(NAME ": start_driver '%s'\n", drv->name);
    452470       
     
    498516 * @param phone         The phone to the driver.
    499517 */
    500 void set_driver_phone(driver_t *driver, ipcarg_t phone)
     518void set_driver_phone(driver_t *driver, sysarg_t phone)
    501519{
    502520        fibril_mutex_lock(&driver->driver_mutex);
     
    508526/** Notify driver about the devices to which it was assigned.
    509527 *
    510  * The driver's mutex must be locked.
    511  *
    512528 * @param driver        The driver to which the devices are passed.
    513529 */
     
    518534        int phone;
    519535
    520         printf(NAME ": pass_devices_to_driver\n");
    521 
    522         phone = ipc_connect_me_to(driver->phone, DRIVER_DEVMAN, 0, 0);
    523         if (phone > 0) {
    524                
     536        printf(NAME ": pass_devices_to_driver(`%s')\n", driver->name);
     537
     538        fibril_mutex_lock(&driver->driver_mutex);
     539
     540        phone = async_connect_me_to(driver->phone, DRIVER_DEVMAN, 0, 0);
     541
     542        if (phone < 0) {
     543                fibril_mutex_unlock(&driver->driver_mutex);
     544                return;
     545        }
     546
     547        /*
     548         * Go through devices list as long as there is some device
     549         * that has not been passed to the driver.
     550         */
     551        link = driver->devices.next;
     552        while (link != &driver->devices) {
     553                dev = list_get_instance(link, node_t, driver_devices);
     554                if (dev->passed_to_driver) {
     555                        link = link->next;
     556                        continue;
     557                }
     558
     559                /*
     560                 * We remove the device from the list to allow safe adding
     561                 * of new devices (no one will touch our item this way).
     562                 */
     563                list_remove(link);
     564
     565                /*
     566                 * Unlock to avoid deadlock when adding device
     567                 * handled by itself.
     568                 */
     569                fibril_mutex_unlock(&driver->driver_mutex);
     570
     571                add_device(phone, driver, dev, tree);
     572
     573                /*
     574                 * Lock again as we will work with driver's
     575                 * structure.
     576                 */
     577                fibril_mutex_lock(&driver->driver_mutex);
     578
     579                /*
     580                 * Insert the device back.
     581                 * The order is not relevant here so no harm is done
     582                 * (actually, the order would be preserved in most cases).
     583                 */
     584                list_append(link, &driver->devices);
     585
     586                /*
     587                 * Restart the cycle to go through all devices again.
     588                 */
    525589                link = driver->devices.next;
    526                 while (link != &driver->devices) {
    527                         dev = list_get_instance(link, node_t, driver_devices);
    528                         add_device(phone, driver, dev, tree);
    529                         link = link->next;
    530                 }
    531                
    532                 ipc_hangup(phone);
    533         }
     590        }
     591
     592        ipc_hangup(phone);
     593
     594        /*
     595         * Once we passed all devices to the driver, we need to mark the
     596         * driver as running.
     597         * It is vital to do it here and inside critical section.
     598         *
     599         * If we would change the state earlier, other devices added to
     600         * the driver would be added to the device list and started
     601         * immediately and possibly started here as well.
     602         */
     603        printf(NAME ": driver %s goes into running state.\n", driver->name);
     604        driver->state = DRIVER_RUNNING;
     605
     606        fibril_mutex_unlock(&driver->driver_mutex);
    534607}
    535608
     
    545618void initialize_running_driver(driver_t *driver, dev_tree_t *tree)
    546619{
    547         printf(NAME ": initialize_running_driver\n");
    548         fibril_mutex_lock(&driver->driver_mutex);
     620        printf(NAME ": initialize_running_driver (`%s')\n", driver->name);
    549621       
    550622        /*
     
    553625         */
    554626        pass_devices_to_driver(driver, tree);
    555        
    556         /* Change driver's state to running. */
    557         driver->state = DRIVER_RUNNING;
    558        
    559         fibril_mutex_unlock(&driver->driver_mutex);
    560627}
    561628
     
    621688        }
    622689       
    623         devmap_device_register(devmap_pathname, &node->devmap_handle);
     690        devmap_device_register_with_iface(devmap_pathname,
     691            &node->devmap_handle, DEVMAN_CONNECT_FROM_DEVMAP);
    624692       
    625693        tree_add_devmap_device(tree, node);
     
    629697}
    630698
    631 
    632699/** Pass a device to running driver.
    633700 *
     
    637704void add_device(int phone, driver_t *drv, node_t *node, dev_tree_t *tree)
    638705{
    639         printf(NAME ": add_device\n");
    640        
    641         ipcarg_t rc;
     706        /*
     707         * We do not expect to have driver's mutex locked as we do not
     708         * access any structures that would affect driver_t.
     709         */
     710        printf(NAME ": add_device (driver `%s', device `%s')\n", drv->name,
     711            node->name);
     712       
     713        sysarg_t rc;
    642714        ipc_call_t answer;
    643715       
    644716        /* Send the device to the driver. */
    645         aid_t req = async_send_1(phone, DRIVER_ADD_DEVICE, node->handle,
    646             &answer);
     717        devman_handle_t parent_handle;
     718        if (node->parent) {
     719                parent_handle = node->parent->handle;
     720        } else {
     721                parent_handle = 0;
     722        }
     723
     724        aid_t req = async_send_2(phone, DRIVER_ADD_DEVICE, node->handle,
     725            parent_handle, &answer);
    647726       
    648727        /* Send the device's name to the driver. */
     
    652731                /* TODO handle error */
    653732        }
    654        
     733
    655734        /* Wait for answer from the driver. */
    656735        async_wait_for(req, &rc);
     736
    657737        switch(rc) {
    658738        case EOK:
     
    667747        }
    668748       
     749        node->passed_to_driver = true;
     750
    669751        return;
    670752}
     
    692774        attach_driver(node, drv);
    693775       
     776        fibril_mutex_lock(&drv->driver_mutex);
    694777        if (drv->state == DRIVER_NOT_STARTED) {
    695778                /* Start the driver. */
    696779                start_driver(drv);
    697780        }
    698        
    699         if (drv->state == DRIVER_RUNNING) {
     781        bool is_running = drv->state == DRIVER_RUNNING;
     782        fibril_mutex_unlock(&drv->driver_mutex);
     783
     784        if (is_running) {
    700785                /* Notify the driver about the new device. */
    701                 int phone = ipc_connect_me_to(drv->phone, DRIVER_DEVMAN, 0, 0);
     786                int phone = async_connect_me_to(drv->phone, DRIVER_DEVMAN, 0, 0);
    702787                if (phone > 0) {
    703788                        add_device(phone, drv, node, tree);
     
    776861/** Find the device node structure of the device witch has the specified handle.
    777862 *
    778  * Device tree's rwlock should be held at least for reading.
    779  *
    780863 * @param tree          The device tree where we look for the device node.
    781864 * @param handle        The handle of the device.
     
    785868{
    786869        unsigned long key = handle;
    787         link_t *link = hash_table_find(&tree->devman_devices, &key);
     870        link_t *link;
     871       
     872        assert(fibril_rwlock_is_locked(&tree->rwlock));
     873       
     874        link = hash_table_find(&tree->devman_devices, &key);
    788875        return hash_table_get_instance(link, node_t, devman_link);
    789876}
     
    841928/** Insert new device into device tree.
    842929 *
    843  * The device tree's rwlock should be already held exclusively when calling this
    844  * function.
    845  *
    846930 * @param tree          The device tree.
    847931 * @param node          The newly added device node.
     
    858942        assert(tree != NULL);
    859943        assert(dev_name != NULL);
     944        assert(fibril_rwlock_is_write_locked(&tree->rwlock));
    860945       
    861946        node->name = dev_name;
    862947        if (!set_dev_path(node, parent)) {
    863                 fibril_rwlock_write_unlock(&tree->rwlock);
    864948                return false;
    865949        }
     
    9771061       
    9781062        info = (dev_class_info_t *) malloc(sizeof(dev_class_info_t));
    979         if (info != NULL)
     1063        if (info != NULL) {
    9801064                memset(info, 0, sizeof(dev_class_info_t));
     1065                list_initialize(&info->dev_classes);
     1066                list_initialize(&info->devmap_link);
     1067                list_initialize(&info->link);
     1068        }
    9811069       
    9821070        return info;
     
    10831171        while (link != &class_list->classes) {
    10841172                cl = list_get_instance(link, dev_class_t, link);
    1085                 if (str_cmp(cl->name, class_name) == 0)
     1173                if (str_cmp(cl->name, class_name) == 0) {
    10861174                        return cl;
     1175                }
     1176                link = link->next;
    10871177        }
    10881178       
     
    11001190        fibril_rwlock_initialize(&class_list->rwlock);
    11011191        hash_table_create(&class_list->devmap_devices, DEVICE_BUCKETS, 1,
    1102             &devmap_devices_ops);
     1192            &devmap_devices_class_ops);
    11031193}
    11041194
     
    11481238        hash_table_insert(&class_list->devmap_devices, &key, &cli->devmap_link);
    11491239        fibril_rwlock_write_unlock(&class_list->rwlock);
     1240
     1241        assert(find_devmap_class_device(class_list, cli->devmap_handle) != NULL);
    11501242}
    11511243
Note: See TracChangeset for help on using the changeset viewer.