Ignore:
File:
1 edited

Legend:

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

    r0d6915f r463e734  
    508508/** Notify driver about the devices to which it was assigned.
    509509 *
    510  * The driver's mutex must be locked.
    511  *
    512510 * @param driver        The driver to which the devices are passed.
    513511 */
     
    518516        int phone;
    519517
    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                
     518        printf(NAME ": pass_devices_to_driver(`%s')\n", driver->name);
     519
     520        fibril_mutex_lock(&driver->driver_mutex);
     521
     522        phone = async_connect_me_to(driver->phone, DRIVER_DEVMAN, 0, 0);
     523
     524        if (phone < 0) {
     525                fibril_mutex_unlock(&driver->driver_mutex);
     526                return;
     527        }
     528
     529        /*
     530         * Go through devices list as long as there is some device
     531         * that has not been passed to the driver.
     532         */
     533        link = driver->devices.next;
     534        while (link != &driver->devices) {
     535                dev = list_get_instance(link, node_t, driver_devices);
     536                if (dev->passed_to_driver) {
     537                        link = link->next;
     538                        continue;
     539                }
     540
     541                /*
     542                 * We remove the device from the list to allow safe adding
     543                 * of new devices (no one will touch our item this way).
     544                 */
     545                list_remove(link);
     546
     547                /*
     548                 * Unlock to avoid deadlock when adding device
     549                 * handled by itself.
     550                 */
     551                fibril_mutex_unlock(&driver->driver_mutex);
     552
     553                add_device(phone, driver, dev, tree);
     554
     555                /*
     556                 * Lock again as we will work with driver's
     557                 * structure.
     558                 */
     559                fibril_mutex_lock(&driver->driver_mutex);
     560
     561                /*
     562                 * Insert the device back.
     563                 * The order is not relevant here so no harm is done
     564                 * (actually, the order would be preserved in most cases).
     565                 */
     566                list_append(link, &driver->devices);
     567
     568                /*
     569                 * Restart the cycle to go through all devices again.
     570                 */
    525571                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         }
     572        }
     573
     574        ipc_hangup(phone);
     575
     576        /*
     577         * Once we passed all devices to the driver, we need to mark the
     578         * driver as running.
     579         * It is vital to do it here and inside critical section.
     580         *
     581         * If we would change the state earlier, other devices added to
     582         * the driver would be added to the device list and started
     583         * immediately and possibly started here as well.
     584         */
     585        printf(NAME ": driver %s goes into running state.\n", driver->name);
     586        driver->state = DRIVER_RUNNING;
     587
     588        fibril_mutex_unlock(&driver->driver_mutex);
    534589}
    535590
     
    545600void initialize_running_driver(driver_t *driver, dev_tree_t *tree)
    546601{
    547         printf(NAME ": initialize_running_driver\n");
    548         fibril_mutex_lock(&driver->driver_mutex);
     602        printf(NAME ": initialize_running_driver (`%s')\n", driver->name);
    549603       
    550604        /*
     
    553607         */
    554608        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);
    560609}
    561610
     
    629678}
    630679
     680static FIBRIL_MUTEX_INITIALIZE(add_device_guard);
    631681
    632682/** Pass a device to running driver.
     
    637687void add_device(int phone, driver_t *drv, node_t *node, dev_tree_t *tree)
    638688{
    639         printf(NAME ": add_device\n");
     689        fibril_mutex_lock(&add_device_guard);
     690
     691        /*
     692         * We do not expect to have driver's mutex locked as we do not
     693         * access any structures that would affect driver_t.
     694         */
     695        printf(NAME ": add_device (driver `%s', device `%s')\n", drv->name,
     696            node->name);
    640697       
    641698        ipcarg_t rc;
     
    649706                parent_handle = 0;
    650707        }
     708
    651709        aid_t req = async_send_2(phone, DRIVER_ADD_DEVICE, node->handle,
    652710            parent_handle, &answer);
     
    658716                /* TODO handle error */
    659717        }
    660        
     718
    661719        /* Wait for answer from the driver. */
    662720        async_wait_for(req, &rc);
     721
     722        fibril_mutex_unlock(&add_device_guard);
     723
    663724        switch(rc) {
    664725        case EOK:
     
    673734        }
    674735       
     736        node->passed_to_driver = true;
     737
    675738        return;
    676739}
     
    698761        attach_driver(node, drv);
    699762       
     763        fibril_mutex_lock(&drv->driver_mutex);
    700764        if (drv->state == DRIVER_NOT_STARTED) {
    701765                /* Start the driver. */
    702766                start_driver(drv);
    703767        }
    704        
    705         if (drv->state == DRIVER_RUNNING) {
     768        fibril_mutex_unlock(&drv->driver_mutex);
     769       
     770        fibril_mutex_lock(&drv->driver_mutex);
     771        bool is_running = drv->state == DRIVER_RUNNING;
     772        fibril_mutex_unlock(&drv->driver_mutex);
     773
     774        if (is_running) {
    706775                /* Notify the driver about the new device. */
    707                 int phone = ipc_connect_me_to(drv->phone, DRIVER_DEVMAN, 0, 0);
     776                int phone = async_connect_me_to(drv->phone, DRIVER_DEVMAN, 0, 0);
    708777                if (phone > 0) {
    709778                        add_device(phone, drv, node, tree);
     
    867936        node->name = dev_name;
    868937        if (!set_dev_path(node, parent)) {
    869                 fibril_rwlock_write_unlock(&tree->rwlock);
    870938                return false;
    871939        }
     
    10201088       
    10211089        size_t idx = get_new_class_dev_idx(cl);
    1022         asprintf(&dev_name, "%s%d", base_name, idx);
     1090        asprintf(&dev_name, "%s%zu", base_name, idx);
    10231091       
    10241092        return dev_name;
     
    10891157        while (link != &class_list->classes) {
    10901158                cl = list_get_instance(link, dev_class_t, link);
    1091                 if (str_cmp(cl->name, class_name) == 0)
     1159                if (str_cmp(cl->name, class_name) == 0) {
    10921160                        return cl;
     1161                }
     1162                link = link->next;
    10931163        }
    10941164       
Note: See TracChangeset for help on using the changeset viewer.