Changeset 4006447 in mainline for uspace/srv


Ignore:
Timestamp:
2010-12-06T20:03:54Z (15 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
c0bd08d
Parents:
b38dfd8 (diff), 463e734 (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:

Merge from lp:~vojtech-horky/helenos/ddf-fixes.

Location:
uspace/srv/devman
Files:
4 edited

Legend:

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

    rb38dfd8 r4006447  
    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;
     
    643700       
    644701        /* Send the device to the driver. */
    645         aid_t req = async_send_1(phone, DRIVER_ADD_DEVICE, node->handle,
    646             &answer);
     702        devman_handle_t parent_handle;
     703        if (node->parent) {
     704                parent_handle = node->parent->handle;
     705        } else {
     706                parent_handle = 0;
     707        }
     708
     709        aid_t req = async_send_2(phone, DRIVER_ADD_DEVICE, node->handle,
     710            parent_handle, &answer);
    647711       
    648712        /* Send the device's name to the driver. */
     
    652716                /* TODO handle error */
    653717        }
    654        
     718
    655719        /* Wait for answer from the driver. */
    656720        async_wait_for(req, &rc);
     721
     722        fibril_mutex_unlock(&add_device_guard);
     723
    657724        switch(rc) {
    658725        case EOK:
     
    667734        }
    668735       
     736        node->passed_to_driver = true;
     737
    669738        return;
    670739}
     
    692761        attach_driver(node, drv);
    693762       
     763        fibril_mutex_lock(&drv->driver_mutex);
    694764        if (drv->state == DRIVER_NOT_STARTED) {
    695765                /* Start the driver. */
    696766                start_driver(drv);
    697767        }
    698        
    699         if (drv->state == DRIVER_RUNNING) {
     768        bool is_running = drv->state == DRIVER_RUNNING;
     769        fibril_mutex_unlock(&drv->driver_mutex);
     770
     771        if (is_running) {
    700772                /* Notify the driver about the new device. */
    701                 int phone = ipc_connect_me_to(drv->phone, DRIVER_DEVMAN, 0, 0);
     773                int phone = async_connect_me_to(drv->phone, DRIVER_DEVMAN, 0, 0);
    702774                if (phone > 0) {
    703775                        add_device(phone, drv, node, tree);
     
    861933        node->name = dev_name;
    862934        if (!set_dev_path(node, parent)) {
    863                 fibril_rwlock_write_unlock(&tree->rwlock);
    864935                return false;
    865936        }
     
    10831154        while (link != &class_list->classes) {
    10841155                cl = list_get_instance(link, dev_class_t, link);
    1085                 if (str_cmp(cl->name, class_name) == 0)
     1156                if (str_cmp(cl->name, class_name) == 0) {
    10861157                        return cl;
     1158                }
     1159                link = link->next;
    10871160        }
    10881161       
  • uspace/srv/devman/devman.h

    rb38dfd8 r4006447  
    168168         */
    169169        link_t devmap_link;
     170
     171        /**
     172         * Whether this device was already passed to the driver.
     173         */
     174        bool passed_to_driver;
    170175};
    171176
  • uspace/srv/devman/main.c

    rb38dfd8 r4006447  
    197197}
    198198
     199static int assign_driver_fibril(void *arg)
     200{
     201        node_t *node = (node_t *) arg;
     202        assign_driver(node, &drivers_list, &device_tree);
     203        return EOK;
     204}
     205
    199206/** Handle child device registration.
    200207 *
     
    237244       
    238245        devman_receive_match_ids(match_count, &node->match_ids);
    239        
     246
     247        /*
     248         * Try to find a suitable driver and assign it to the device.  We do
     249         * not want to block the current fibril that is used for processing
     250         * incoming calls: we will launch a separate fibril to handle the
     251         * driver assigning. That is because assign_driver can actually include
     252         * task spawning which could take some time.
     253         */
     254        fid_t assign_fibril = fibril_create(assign_driver_fibril, node);
     255        if (assign_fibril == 0) {
     256                /*
     257                 * Fallback in case we are out of memory.
     258                 * Probably not needed as we will die soon anyway ;-).
     259                 */
     260                (void) assign_driver_fibril(node);
     261        } else {
     262                fibril_add_ready(assign_fibril);
     263        }
     264
    240265        /* Return device handle to parent's driver. */
    241266        ipc_answer_1(callid, EOK, node->handle);
    242        
    243         /* Try to find suitable driver and assign it to the device. */
    244         assign_driver(node, &drivers_list, &device_tree);
    245267}
    246268
     
    297319        printf(NAME ": device '%s' added to class '%s', class name '%s' was "
    298320            "asigned to it\n", dev->pathname, class_name, class_info->dev_name);
    299        
     321
    300322        ipc_answer_0(callid, EOK);
    301323}
  • uspace/srv/devman/match.c

    rb38dfd8 r4006447  
    3535#include "devman.h"
    3636
     37/** Compute compound score of driver and device.
     38 *
     39 * @param driver Match id of the driver.
     40 * @param device Match id of the device.
     41 * @return Compound score.
     42 * @retval 0 No match at all.
     43 */
     44static int compute_match_score(match_id_t *driver, match_id_t *device)
     45{
     46        if (str_cmp(driver->id, device->id) == 0) {
     47                /*
     48                 * The strings match, return the product of their scores.
     49                 */
     50                return driver->score * device->score;
     51        } else {
     52                /*
     53                 * Different strings, return zero.
     54                 */
     55                return 0;
     56        }
     57}
     58
    3759int get_match_score(driver_t *drv, node_t *dev)
    3860{
     
    4365                return 0;
    4466       
     67        /*
     68         * Go through all pairs, return the highest score obtained.
     69         */
     70        int highest_score = 0;
     71       
    4572        link_t *drv_link = drv->match_ids.ids.next;
    46         link_t *dev_link = dev->match_ids.ids.next;
    47        
    48         match_id_t *drv_id = list_get_instance(drv_link, match_id_t, link);
    49         match_id_t *dev_id = list_get_instance(dev_link, match_id_t, link);
    50        
    51         int score_next_drv = 0;
    52         int score_next_dev = 0;
    53        
    54         do {
    55                 match_id_t *tmp_ma_id;
    56        
    57                 if (str_cmp(drv_id->id, dev_id->id) == 0) {
    58                         /*
    59                          * We found a match.
    60                          * Return the score of the match.
    61                          */
    62                         return drv_id->score * dev_id->score;
     73        while (drv_link != drv_head) {
     74                link_t *dev_link = dev_head->next;
     75                while (dev_link != dev_head) {
     76                        match_id_t *drv_id = list_get_instance(drv_link, match_id_t, link);
     77                        match_id_t *dev_id = list_get_instance(dev_link, match_id_t, link);
     78                       
     79                        int score = compute_match_score(drv_id, dev_id);
     80                        if (score > highest_score) {
     81                                highest_score = score;
     82                        }
     83
     84                        dev_link = dev_link->next;
    6385                }
    6486               
    65                 /*
    66                  * Compute the next score we get, if we advance in the driver's
    67                  * list of match ids.
    68                  */
    69                 if (drv_link->next != drv_head) {
    70                         tmp_ma_id = list_get_instance(drv_link->next,
    71                             match_id_t, link);
    72                         score_next_drv = dev_id->score * tmp_ma_id->score;
    73                 } else {
    74                         score_next_drv = 0;
    75                 }
    76                
    77                 /*
    78                  * Compute the next score we get, if we advance in the device's
    79                  * list of match ids.
    80                  */
    81                 if (dev_link->next != dev_head) {
    82                         tmp_ma_id = list_get_instance(dev_link->next,
    83                             match_id_t, link);
    84                         score_next_dev = drv_id->score * tmp_ma_id->score;
    85                 } else {
    86                         score_next_dev = 0;
    87                 }
    88                
    89                 /*
    90                  * Advance in one of the two lists, so we get the next highest
    91                  * score.
    92                  */
    93                 if (score_next_drv > score_next_dev) {
    94                         drv_link = drv_link->next;
    95                         drv_id = list_get_instance(drv_link, match_id_t, link);
    96                 } else {
    97                         dev_link = dev_link->next;
    98                         dev_id = list_get_instance(dev_link, match_id_t, link);
    99                 }
    100                
    101         } while (drv_link->next != drv_head && dev_link->next != dev_head);
     87                drv_link = drv_link->next;
     88        }
    10289       
    103         return 0;
     90        return highest_score;
    10491}
    10592
Note: See TracChangeset for help on using the changeset viewer.