Changeset 02e5e34 in mainline


Ignore:
Timestamp:
2013-09-10T21:27:30Z (11 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
a501e22c
Parents:
181c32f
Message:

Fun on-/off-line needs to go to fun.c

Location:
uspace/srv/devman
Files:
3 edited

Legend:

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

    r181c32f r02e5e34  
    3636 */
    3737
    38 #include <inttypes.h>
    3938#include <assert.h>
    4039#include <ipc/services.h>
     
    4847#include <stdlib.h>
    4948#include <str.h>
    50 #include <dirent.h>
    51 #include <fcntl.h>
    52 #include <sys/stat.h>
    53 #include <ctype.h>
    5449#include <io/log.h>
    5550#include <ipc/devman.h>
    5651#include <ipc/driver.h>
    57 #include <thread.h>
    5852#include <loc.h>
    5953
     
    233227}
    234228
    235 static int assign_driver_fibril(void *arg)
    236 {
    237         dev_node_t *dev_node = (dev_node_t *) arg;
    238         assign_driver(dev_node, &drivers_list, &device_tree);
    239 
    240         /* Delete one reference we got from the caller. */
    241         dev_del_ref(dev_node);
    242         return EOK;
    243 }
    244 
    245 static int online_function(fun_node_t *fun)
    246 {
    247         dev_node_t *dev;
    248        
    249         fibril_rwlock_write_lock(&device_tree.rwlock);
    250        
    251         if (fun->state == FUN_ON_LINE) {
    252                 fibril_rwlock_write_unlock(&device_tree.rwlock);
    253                 log_msg(LOG_DEFAULT, LVL_WARN, "Function %s is already on line.",
    254                     fun->pathname);
    255                 return EOK;
    256         }
    257        
    258         if (fun->ftype == fun_inner) {
    259                 dev = create_dev_node();
    260                 if (dev == NULL) {
    261                         fibril_rwlock_write_unlock(&device_tree.rwlock);
    262                         return ENOMEM;
    263                 }
    264                
    265                 insert_dev_node(&device_tree, dev, fun);
    266                 dev_add_ref(dev);
    267         }
    268        
    269         log_msg(LOG_DEFAULT, LVL_DEBUG, "devman_add_function(fun=\"%s\")", fun->pathname);
    270        
    271         if (fun->ftype == fun_inner) {
    272                 dev = fun->child;
    273                 assert(dev != NULL);
    274                
    275                 /* Give one reference over to assign_driver_fibril(). */
    276                 dev_add_ref(dev);
    277                
    278                 /*
    279                  * Try to find a suitable driver and assign it to the device.  We do
    280                  * not want to block the current fibril that is used for processing
    281                  * incoming calls: we will launch a separate fibril to handle the
    282                  * driver assigning. That is because assign_driver can actually include
    283                  * task spawning which could take some time.
    284                  */
    285                 fid_t assign_fibril = fibril_create(assign_driver_fibril, dev);
    286                 if (assign_fibril == 0) {
    287                         log_msg(LOG_DEFAULT, LVL_ERROR, "Failed to create fibril for "
    288                             "assigning driver.");
    289                         /* XXX Cleanup */
    290                         fibril_rwlock_write_unlock(&device_tree.rwlock);
    291                         return ENOMEM;
    292                 }
    293                 fibril_add_ready(assign_fibril);
    294         } else
    295                 loc_register_tree_function(fun, &device_tree);
    296        
    297         fibril_rwlock_write_unlock(&device_tree.rwlock);
    298        
    299         return EOK;
    300 }
    301 
    302 static int offline_function(fun_node_t *fun)
    303 {
    304         int rc;
    305        
    306         fibril_rwlock_write_lock(&device_tree.rwlock);
    307        
    308         if (fun->state == FUN_OFF_LINE) {
    309                 fibril_rwlock_write_unlock(&device_tree.rwlock);
    310                 log_msg(LOG_DEFAULT, LVL_WARN, "Function %s is already off line.",
    311                     fun->pathname);
    312                 return EOK;
    313         }
    314        
    315         if (fun->ftype == fun_inner) {
    316                 log_msg(LOG_DEFAULT, LVL_DEBUG, "Offlining inner function %s.",
    317                     fun->pathname);
    318                
    319                 if (fun->child != NULL) {
    320                         dev_node_t *dev = fun->child;
    321                         device_state_t dev_state;
    322                        
    323                         dev_add_ref(dev);
    324                         dev_state = dev->state;
    325                        
    326                         fibril_rwlock_write_unlock(&device_tree.rwlock);
    327 
    328                         /* If device is owned by driver, ask driver to give it up. */
    329                         if (dev_state == DEVICE_USABLE) {
    330                                 rc = driver_dev_remove(&device_tree, dev);
    331                                 if (rc != EOK) {
    332                                         dev_del_ref(dev);
    333                                         return ENOTSUP;
    334                                 }
    335                         }
    336                        
    337                         /* Verify that driver removed all functions */
    338                         fibril_rwlock_read_lock(&device_tree.rwlock);
    339                         if (!list_empty(&dev->functions)) {
    340                                 fibril_rwlock_read_unlock(&device_tree.rwlock);
    341                                 dev_del_ref(dev);
    342                                 return EIO;
    343                         }
    344                        
    345                         driver_t *driver = dev->drv;
    346                         fibril_rwlock_read_unlock(&device_tree.rwlock);
    347                        
    348                         if (driver)
    349                                 detach_driver(&device_tree, dev);
    350                        
    351                         fibril_rwlock_write_lock(&device_tree.rwlock);
    352                         remove_dev_node(&device_tree, dev);
    353                        
    354                         /* Delete ref created when node was inserted */
    355                         dev_del_ref(dev);
    356                         /* Delete ref created by dev_add_ref(dev) above */
    357                         dev_del_ref(dev);
    358                 }
    359         } else {
    360                 /* Unregister from location service */
    361                 rc = loc_service_unregister(fun->service_id);
    362                 if (rc != EOK) {
    363                         fibril_rwlock_write_unlock(&device_tree.rwlock);
    364                         log_msg(LOG_DEFAULT, LVL_ERROR, "Failed unregistering tree service.");
    365                         return EIO;
    366                 }
    367                
    368                 fun->service_id = 0;
    369         }
    370        
    371         fun->state = FUN_OFF_LINE;
    372         fibril_rwlock_write_unlock(&device_tree.rwlock);
    373        
    374         return EOK;
    375 }
    376 
    377229/** Handle function registration.
    378230 *
     
    461313        devman_receive_match_ids(match_count, &fun->match_ids);
    462314       
    463         rc = online_function(fun);
     315        rc = fun_online(fun);
    464316        if (rc != EOK) {
    465317                /* XXX Set some failed state? */
     
    552404        fibril_rwlock_read_unlock(&device_tree.rwlock);
    553405       
    554         rc = online_function(fun);
     406        rc = fun_offline(fun);
    555407        if (rc != EOK) {
    556408                fun_busy_unlock(fun);
     
    593445        fibril_rwlock_write_unlock(&device_tree.rwlock);
    594446       
    595         rc = offline_function(fun);
     447        rc = fun_offline(fun);
    596448        if (rc != EOK) {
    597449                fun_busy_unlock(fun);
  • uspace/srv/devman/fun.c

    r181c32f r02e5e34  
    3333#include <errno.h>
    3434#include <io/log.h>
    35 
     35#include <loc.h>
     36
     37#include "dev.h"
    3638#include "devman.h"
     39#include "devtree.h"
     40#include "driver.h"
    3741#include "fun.h"
     42#include "main.h"
     43#include "loc.h"
    3844
    3945static fun_node_t *find_node_child(dev_tree_t *, fun_node_t *, const char *);
     
    280286}
    281287
     288static int assign_driver_fibril(void *arg)
     289{
     290        dev_node_t *dev_node = (dev_node_t *) arg;
     291        assign_driver(dev_node, &drivers_list, &device_tree);
     292
     293        /* Delete one reference we got from the caller. */
     294        dev_del_ref(dev_node);
     295        return EOK;
     296}
     297
     298int fun_online(fun_node_t *fun)
     299{
     300        dev_node_t *dev;
     301       
     302        fibril_rwlock_write_lock(&device_tree.rwlock);
     303       
     304        if (fun->state == FUN_ON_LINE) {
     305                fibril_rwlock_write_unlock(&device_tree.rwlock);
     306                log_msg(LOG_DEFAULT, LVL_WARN, "Function %s is already on line.",
     307                    fun->pathname);
     308                return EOK;
     309        }
     310       
     311        if (fun->ftype == fun_inner) {
     312                dev = create_dev_node();
     313                if (dev == NULL) {
     314                        fibril_rwlock_write_unlock(&device_tree.rwlock);
     315                        return ENOMEM;
     316                }
     317               
     318                insert_dev_node(&device_tree, dev, fun);
     319                dev_add_ref(dev);
     320        }
     321       
     322        log_msg(LOG_DEFAULT, LVL_DEBUG, "devman_add_function(fun=\"%s\")", fun->pathname);
     323       
     324        if (fun->ftype == fun_inner) {
     325                dev = fun->child;
     326                assert(dev != NULL);
     327               
     328                /* Give one reference over to assign_driver_fibril(). */
     329                dev_add_ref(dev);
     330               
     331                /*
     332                 * Try to find a suitable driver and assign it to the device.  We do
     333                 * not want to block the current fibril that is used for processing
     334                 * incoming calls: we will launch a separate fibril to handle the
     335                 * driver assigning. That is because assign_driver can actually include
     336                 * task spawning which could take some time.
     337                 */
     338                fid_t assign_fibril = fibril_create(assign_driver_fibril, dev);
     339                if (assign_fibril == 0) {
     340                        log_msg(LOG_DEFAULT, LVL_ERROR, "Failed to create fibril for "
     341                            "assigning driver.");
     342                        /* XXX Cleanup */
     343                        fibril_rwlock_write_unlock(&device_tree.rwlock);
     344                        return ENOMEM;
     345                }
     346                fibril_add_ready(assign_fibril);
     347        } else
     348                loc_register_tree_function(fun, &device_tree);
     349       
     350        fibril_rwlock_write_unlock(&device_tree.rwlock);
     351       
     352        return EOK;
     353}
     354
     355int fun_offline(fun_node_t *fun)
     356{
     357        int rc;
     358       
     359        fibril_rwlock_write_lock(&device_tree.rwlock);
     360       
     361        if (fun->state == FUN_OFF_LINE) {
     362                fibril_rwlock_write_unlock(&device_tree.rwlock);
     363                log_msg(LOG_DEFAULT, LVL_WARN, "Function %s is already off line.",
     364                    fun->pathname);
     365                return EOK;
     366        }
     367       
     368        if (fun->ftype == fun_inner) {
     369                log_msg(LOG_DEFAULT, LVL_DEBUG, "Offlining inner function %s.",
     370                    fun->pathname);
     371               
     372                if (fun->child != NULL) {
     373                        dev_node_t *dev = fun->child;
     374                        device_state_t dev_state;
     375                       
     376                        dev_add_ref(dev);
     377                        dev_state = dev->state;
     378                       
     379                        fibril_rwlock_write_unlock(&device_tree.rwlock);
     380
     381                        /* If device is owned by driver, ask driver to give it up. */
     382                        if (dev_state == DEVICE_USABLE) {
     383                                rc = driver_dev_remove(&device_tree, dev);
     384                                if (rc != EOK) {
     385                                        dev_del_ref(dev);
     386                                        return ENOTSUP;
     387                                }
     388                        }
     389                       
     390                        /* Verify that driver removed all functions */
     391                        fibril_rwlock_read_lock(&device_tree.rwlock);
     392                        if (!list_empty(&dev->functions)) {
     393                                fibril_rwlock_read_unlock(&device_tree.rwlock);
     394                                dev_del_ref(dev);
     395                                return EIO;
     396                        }
     397                       
     398                        driver_t *driver = dev->drv;
     399                        fibril_rwlock_read_unlock(&device_tree.rwlock);
     400                       
     401                        if (driver)
     402                                detach_driver(&device_tree, dev);
     403                       
     404                        fibril_rwlock_write_lock(&device_tree.rwlock);
     405                        remove_dev_node(&device_tree, dev);
     406                       
     407                        /* Delete ref created when node was inserted */
     408                        dev_del_ref(dev);
     409                        /* Delete ref created by dev_add_ref(dev) above */
     410                        dev_del_ref(dev);
     411                }
     412        } else {
     413                /* Unregister from location service */
     414                rc = loc_service_unregister(fun->service_id);
     415                if (rc != EOK) {
     416                        fibril_rwlock_write_unlock(&device_tree.rwlock);
     417                        log_msg(LOG_DEFAULT, LVL_ERROR, "Failed unregistering tree service.");
     418                        return EIO;
     419                }
     420               
     421                fun->service_id = 0;
     422        }
     423       
     424        fun->state = FUN_OFF_LINE;
     425        fibril_rwlock_write_unlock(&device_tree.rwlock);
     426       
     427        return EOK;
     428}
     429
    282430/** @}
    283431 */
  • uspace/srv/devman/fun.h

    r181c32f r02e5e34  
    4949    const char *);
    5050extern bool set_fun_path(dev_tree_t *, fun_node_t *, fun_node_t *);
     51extern int fun_online(fun_node_t *);
     52extern int fun_offline(fun_node_t *);
    5153
    5254#endif
Note: See TracChangeset for help on using the changeset viewer.