Changeset a1b7e80 in mainline for uspace/srv/devman/main.c


Ignore:
Timestamp:
2011-09-02T16:54:18Z (13 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
f480d7e
Parents:
7a72ce1a (diff), 224c0e7 (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 basic infrastructure for anticipated device removal from
lp:~jsvoboda/helenos/devrem

File:
1 edited

Legend:

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

    r7a72ce1a ra1b7e80  
    234234        dev_node_t *dev_node = (dev_node_t *) arg;
    235235        assign_driver(dev_node, &drivers_list, &device_tree);
     236
     237        /* Delete one reference we got from the caller. */
     238        dev_del_ref(dev_node);
    236239        return EOK;
    237240}
    238241
    239 /** Handle function registration.
    240  *
    241  * Child devices are registered by their parent's device driver.
    242  */
    243 static void devman_add_function(ipc_callid_t callid, ipc_call_t *call)
    244 {
    245         fun_type_t ftype = (fun_type_t) IPC_GET_ARG1(*call);
    246         devman_handle_t dev_handle = IPC_GET_ARG2(*call);
    247         sysarg_t match_count = IPC_GET_ARG3(*call);
    248         dev_tree_t *tree = &device_tree;
    249        
    250         fibril_rwlock_write_lock(&tree->rwlock);
    251 
    252         dev_node_t *dev = NULL;
    253         dev_node_t *pdev = find_dev_node_no_lock(&device_tree, dev_handle);
    254        
    255         if (pdev == NULL) {
    256                 fibril_rwlock_write_unlock(&tree->rwlock);
    257                 async_answer_0(callid, ENOENT);
    258                 return;
    259         }
    260        
    261         if (ftype != fun_inner && ftype != fun_exposed) {
    262                 /* Unknown function type */
    263                 log_msg(LVL_ERROR,
    264                     "Unknown function type %d provided by driver.",
    265                     (int) ftype);
    266 
    267                 fibril_rwlock_write_unlock(&tree->rwlock);
    268                 async_answer_0(callid, EINVAL);
    269                 return;
    270         }
    271        
    272         char *fun_name = NULL;
    273         int rc = async_data_write_accept((void **)&fun_name, true, 0, 0, 0, 0);
    274         if (rc != EOK) {
    275                 fibril_rwlock_write_unlock(&tree->rwlock);
    276                 async_answer_0(callid, rc);
    277                 return;
    278         }
    279        
    280         /* Check that function with same name is not there already. */
    281         if (find_fun_node_in_device(pdev, fun_name) != NULL) {
    282                 fibril_rwlock_write_unlock(&tree->rwlock);
    283                 async_answer_0(callid, EEXISTS);
    284                 printf(NAME ": Warning, driver tried to register `%s' twice.\n",
    285                     fun_name);
    286                 free(fun_name);
    287                 return;
    288         }
    289        
    290         fun_node_t *fun = create_fun_node();
    291         fun->ftype = ftype;
    292        
    293         if (!insert_fun_node(&device_tree, fun, fun_name, pdev)) {
    294                 fibril_rwlock_write_unlock(&tree->rwlock);
    295                 delete_fun_node(fun);
    296                 async_answer_0(callid, ENOMEM);
    297                 return;
    298         }
    299 
    300         if (ftype == fun_inner) {
     242static int online_function(fun_node_t *fun)
     243{
     244        dev_node_t *dev;
     245       
     246        fibril_rwlock_write_lock(&device_tree.rwlock);
     247
     248        if (fun->state == FUN_ON_LINE) {
     249                fibril_rwlock_write_unlock(&device_tree.rwlock);
     250                log_msg(LVL_WARN, "Function %s is already on line.",
     251                    fun->pathname);
     252                return EOK;
     253        }
     254       
     255        if (fun->ftype == fun_inner) {
    301256                dev = create_dev_node();
    302257                if (dev == NULL) {
    303                         fibril_rwlock_write_unlock(&tree->rwlock);
    304                         delete_fun_node(fun);
    305                         async_answer_0(callid, ENOMEM);
    306                         return;
     258                        fibril_rwlock_write_unlock(&device_tree.rwlock);
     259                        return ENOMEM;
    307260                }
    308261
    309                 insert_dev_node(tree, dev, fun);
    310         }
    311 
    312         fibril_rwlock_write_unlock(&tree->rwlock);
     262                insert_dev_node(&device_tree, dev, fun);
     263                dev_add_ref(dev);
     264        }
    313265       
    314266        log_msg(LVL_DEBUG, "devman_add_function(fun=\"%s\")", fun->pathname);
    315267       
    316         devman_receive_match_ids(match_count, &fun->match_ids);
    317 
    318         if (ftype == fun_inner) {
     268        if (fun->ftype == fun_inner) {
     269                dev = fun->child;
    319270                assert(dev != NULL);
     271               
     272                /* Give one reference over to assign_driver_fibril(). */
     273                dev_add_ref(dev);
    320274                /*
    321275                 * Try to find a suitable driver and assign it to the device.  We do
     
    327281                fid_t assign_fibril = fibril_create(assign_driver_fibril, dev);
    328282                if (assign_fibril == 0) {
    329                         /*
    330                          * Fallback in case we are out of memory.
    331                          * Probably not needed as we will die soon anyway ;-).
    332                          */
    333                         (void) assign_driver_fibril(fun);
    334                 } else {
    335                         fibril_add_ready(assign_fibril);
     283                        log_msg(LVL_ERROR, "Failed to create fibril for "
     284                            "assigning driver.");
     285                        /* XXX Cleanup */
     286                        fibril_rwlock_write_unlock(&device_tree.rwlock);
     287                        return ENOMEM;
     288                }
     289                fibril_add_ready(assign_fibril);
     290        } else {
     291                loc_register_tree_function(fun, &device_tree);
     292        }
     293       
     294        fibril_rwlock_write_unlock(&device_tree.rwlock);
     295       
     296        return EOK;
     297}
     298
     299static int offline_function(fun_node_t *fun)
     300{
     301        int rc;
     302       
     303        fibril_rwlock_write_lock(&device_tree.rwlock);
     304       
     305        if (fun->state == FUN_OFF_LINE) {
     306                fibril_rwlock_write_unlock(&device_tree.rwlock);
     307                log_msg(LVL_WARN, "Function %s is already off line.",
     308                    fun->pathname);
     309                return EOK;
     310        }
     311       
     312        if (fun->ftype == fun_inner) {
     313                log_msg(LVL_DEBUG, "Offlining inner function %s.",
     314                    fun->pathname);
     315               
     316                if (fun->child != NULL) {
     317                        dev_node_t *dev = fun->child;
     318                       
     319                        dev_add_ref(dev);
     320                        fibril_rwlock_write_unlock(&device_tree.rwlock);
     321                       
     322                        rc = driver_dev_remove(&device_tree, dev);
     323                        if (rc != EOK) {
     324                                dev_del_ref(dev);
     325                                return ENOTSUP;
     326                        }
     327                       
     328                        detach_driver(&device_tree, dev);
     329                       
     330                        fibril_rwlock_write_lock(&device_tree.rwlock);
     331                        remove_dev_node(&device_tree, dev);
     332                       
     333                        /* Delete ref created when node was inserted */
     334                        dev_del_ref(dev);
     335                        /* Delete ref created by dev_add_ref(dev) above */
     336                        dev_del_ref(dev);
    336337                }
    337338        } else {
    338                 loc_register_tree_function(fun, tree);
     339                /* Unregister from location service */
     340                rc = loc_service_unregister(fun->service_id);
     341                if (rc != EOK) {
     342                        fibril_rwlock_write_unlock(&device_tree.rwlock);
     343                        log_msg(LVL_ERROR, "Failed unregistering tree service.");
     344                        return EIO;
     345                }
     346               
     347                fun->service_id = 0;
     348        }
     349       
     350        fun->state = FUN_OFF_LINE;
     351        fibril_rwlock_write_unlock(&device_tree.rwlock);
     352       
     353        return EOK;
     354}
     355
     356/** Handle function registration.
     357 *
     358 * Child devices are registered by their parent's device driver.
     359 */
     360static void devman_add_function(ipc_callid_t callid, ipc_call_t *call)
     361{
     362        fun_type_t ftype = (fun_type_t) IPC_GET_ARG1(*call);
     363        devman_handle_t dev_handle = IPC_GET_ARG2(*call);
     364        sysarg_t match_count = IPC_GET_ARG3(*call);
     365        dev_tree_t *tree = &device_tree;
     366       
     367        dev_node_t *pdev = find_dev_node(&device_tree, dev_handle);
     368        if (pdev == NULL) {
     369                async_answer_0(callid, ENOENT);
     370                return;
     371        }
     372       
     373        if (ftype != fun_inner && ftype != fun_exposed) {
     374                /* Unknown function type */
     375                log_msg(LVL_ERROR,
     376                    "Unknown function type %d provided by driver.",
     377                    (int) ftype);
     378
     379                dev_del_ref(pdev);
     380                async_answer_0(callid, EINVAL);
     381                return;
     382        }
     383       
     384        char *fun_name = NULL;
     385        int rc = async_data_write_accept((void **)&fun_name, true, 0, 0, 0, 0);
     386        if (rc != EOK) {
     387                dev_del_ref(pdev);
     388                async_answer_0(callid, rc);
     389                return;
     390        }
     391       
     392        fibril_rwlock_write_lock(&tree->rwlock);
     393       
     394        /* Check device state */
     395        if (pdev->state == DEVICE_REMOVED) {
     396                fibril_rwlock_write_unlock(&tree->rwlock);
     397                dev_del_ref(pdev);
     398                async_answer_0(callid, ENOENT);
     399                return;
     400        }
     401       
     402        /* Check that function with same name is not there already. */
     403        if (find_fun_node_in_device(tree, pdev, fun_name) != NULL) {
     404                fibril_rwlock_write_unlock(&tree->rwlock);
     405                dev_del_ref(pdev);
     406                async_answer_0(callid, EEXISTS);
     407                printf(NAME ": Warning, driver tried to register `%s' twice.\n",
     408                    fun_name);
     409                free(fun_name);
     410                return;
     411        }
     412       
     413        fun_node_t *fun = create_fun_node();
     414        fun_add_ref(fun);
     415        fun->ftype = ftype;
     416       
     417        if (!insert_fun_node(&device_tree, fun, fun_name, pdev)) {
     418                fibril_rwlock_write_unlock(&tree->rwlock);
     419                dev_del_ref(pdev);
     420                delete_fun_node(fun);
     421                async_answer_0(callid, ENOMEM);
     422                return;
     423        }
     424       
     425        fibril_rwlock_write_unlock(&tree->rwlock);
     426        dev_del_ref(pdev);
     427       
     428        devman_receive_match_ids(match_count, &fun->match_ids);
     429       
     430        rc = online_function(fun);
     431        if (rc != EOK) {
     432                /* XXX clean up */
     433                async_answer_0(callid, rc);
     434                return;
    339435        }
    340436       
     
    356452                async_answer_0(callid, rc);
    357453                return;
    358         }       
     454        }
    359455       
    360456        fun_node_t *fun = find_fun_node(&device_tree, handle);
    361457        if (fun == NULL) {
     458                async_answer_0(callid, ENOENT);
     459                return;
     460        }
     461       
     462        fibril_rwlock_read_lock(&device_tree.rwlock);
     463       
     464        /* Check function state */
     465        if (fun->state == FUN_REMOVED) {
     466                fibril_rwlock_read_unlock(&device_tree.rwlock);
    362467                async_answer_0(callid, ENOENT);
    363468                return;
     
    375480            fun->pathname, cat_name);
    376481
     482        fibril_rwlock_read_unlock(&device_tree.rwlock);
     483        fun_del_ref(fun);
     484
    377485        async_answer_0(callid, EOK);
     486}
     487
     488/** Online function by driver request.
     489 *
     490 */
     491static void devman_drv_fun_online(ipc_callid_t iid, ipc_call_t *icall,
     492    driver_t *drv)
     493{
     494        fun_node_t *fun;
     495        int rc;
     496
     497        printf("devman_drv_fun_online()\n");
     498        fun = find_fun_node(&device_tree, IPC_GET_ARG1(*icall));
     499        if (fun == NULL) {
     500                async_answer_0(iid, ENOENT);
     501                return;
     502        }
     503       
     504        fibril_rwlock_read_lock(&device_tree.rwlock);
     505        if (fun->dev == NULL || fun->dev->drv != drv) {
     506                fibril_rwlock_read_unlock(&device_tree.rwlock);
     507                fun_del_ref(fun);
     508                async_answer_0(iid, ENOENT);
     509                return;
     510        }
     511        fibril_rwlock_read_unlock(&device_tree.rwlock);
     512       
     513        rc = online_function(fun);
     514        if (rc != EOK) {
     515                printf("devman_drv_fun_online() online_fun->ERROR\n");
     516                fun_del_ref(fun);
     517                async_answer_0(iid, (sysarg_t) rc);
     518                return;
     519        }
     520       
     521        fun_del_ref(fun);
     522        printf("devman_drv_fun_online() online_fun->OK\n");
     523       
     524        async_answer_0(iid, (sysarg_t) EOK);
     525}
     526
     527
     528/** Offline function by driver request.
     529 *
     530 */
     531static void devman_drv_fun_offline(ipc_callid_t iid, ipc_call_t *icall,
     532    driver_t *drv)
     533{
     534        fun_node_t *fun;
     535        int rc;
     536
     537        fun = find_fun_node(&device_tree, IPC_GET_ARG1(*icall));
     538        if (fun == NULL) {
     539                async_answer_0(iid, ENOENT);
     540                return;
     541        }
     542       
     543        fibril_rwlock_write_lock(&device_tree.rwlock);
     544        if (fun->dev == NULL || fun->dev->drv != drv) {
     545                fun_del_ref(fun);
     546                async_answer_0(iid, ENOENT);
     547                return;
     548        }
     549        fibril_rwlock_write_unlock(&device_tree.rwlock);
     550       
     551        rc = offline_function(fun);
     552        if (rc != EOK) {
     553                fun_del_ref(fun);
     554                async_answer_0(iid, (sysarg_t) rc);
     555                return;
     556        }
     557       
     558        fun_del_ref(fun);
     559        async_answer_0(iid, (sysarg_t) EOK);
    378560}
    379561
     
    385567        int rc;
    386568       
     569       
     570        fun_node_t *fun = find_fun_node(&device_tree, fun_handle);
     571        if (fun == NULL) {
     572                async_answer_0(callid, ENOENT);
     573                return;
     574        }
     575       
    387576        fibril_rwlock_write_lock(&tree->rwlock);
    388577       
    389         fun_node_t *fun = find_fun_node_no_lock(&device_tree, fun_handle);
    390         if (fun == NULL) {
     578        log_msg(LVL_DEBUG, "devman_remove_function(fun='%s')", fun->pathname);
     579       
     580        /* Check function state */
     581        if (fun->state == FUN_REMOVED) {
    391582                fibril_rwlock_write_unlock(&tree->rwlock);
    392583                async_answer_0(callid, ENOENT);
     
    394585        }
    395586       
    396         log_msg(LVL_DEBUG, "devman_remove_function(fun='%s')", fun->pathname);
    397        
    398587        if (fun->ftype == fun_inner) {
    399588                /* Handle possible descendants */
    400                 /* TODO */
    401                 log_msg(LVL_WARN, "devman_remove_function(): not handling "
    402                     "descendants\n");
     589                /* TODO - This is a surprise removal */
     590                if (fun->child != NULL) {
     591                        log_msg(LVL_WARN, "devman_remove_function(): not handling "
     592                            "descendants\n");
     593                }
    403594        } else {
    404                 /* Unregister from location service */
    405                 rc = loc_service_unregister(fun->service_id);
    406                 if (rc != EOK) {
    407                         log_msg(LVL_ERROR, "Failed unregistering tree service.");
    408                         fibril_rwlock_write_unlock(&tree->rwlock);
    409                         async_answer_0(callid, EIO);
    410                         return;
     595                if (fun->service_id != 0) {
     596                        /* Unregister from location service */
     597                        rc = loc_service_unregister(fun->service_id);
     598                        if (rc != EOK) {
     599                                log_msg(LVL_ERROR, "Failed unregistering tree "
     600                                    "service.");
     601                                fibril_rwlock_write_unlock(&tree->rwlock);
     602                                fun_del_ref(fun);
     603                                async_answer_0(callid, EIO);
     604                                return;
     605                        }
    411606                }
    412607        }
     
    414609        remove_fun_node(&device_tree, fun);
    415610        fibril_rwlock_write_unlock(&tree->rwlock);
    416         delete_fun_node(fun);
     611       
     612        /* Delete ref added when inserting function into tree */
     613        fun_del_ref(fun);
     614        /* Delete ref added above when looking up function */
     615        fun_del_ref(fun);
    417616       
    418617        log_msg(LVL_DEBUG, "devman_remove_function() succeeded.");
     
    485684                        devman_add_function_to_cat(callid, &call);
    486685                        break;
     686                case DEVMAN_DRV_FUN_ONLINE:
     687                        devman_drv_fun_online(callid, &call, driver);
     688                        break;
     689                case DEVMAN_DRV_FUN_OFFLINE:
     690                        devman_drv_fun_offline(callid, &call, driver);
     691                        break;
    487692                case DEVMAN_REMOVE_FUNCTION:
    488693                        devman_remove_function(callid, &call);
    489694                        break;
    490695                default:
    491                         async_answer_0(callid, EINVAL); 
     696                        async_answer_0(callid, EINVAL);
    492697                        break;
    493698                }
     
    500705{
    501706        char *pathname;
     707        devman_handle_t handle;
    502708       
    503709        int rc = async_data_write_accept((void **) &pathname, true, 0, 0, 0, 0);
     
    516722        }
    517723
    518         async_answer_1(iid, EOK, fun->handle);
     724        fibril_rwlock_read_lock(&device_tree.rwlock);
     725
     726        /* Check function state */
     727        if (fun->state == FUN_REMOVED) {
     728                fibril_rwlock_read_unlock(&device_tree.rwlock);
     729                async_answer_0(iid, ENOENT);
     730                return;
     731        }
     732        handle = fun->handle;
     733
     734        fibril_rwlock_read_unlock(&device_tree.rwlock);
     735
     736        /* Delete reference created above by find_fun_node_by_path() */
     737        fun_del_ref(fun);
     738
     739        async_answer_1(iid, EOK, handle);
    519740}
    520741
     
    534755        if (!async_data_read_receive(&data_callid, &data_len)) {
    535756                async_answer_0(iid, EINVAL);
     757                fun_del_ref(fun);
    536758                return;
    537759        }
     
    541763                async_answer_0(data_callid, ENOMEM);
    542764                async_answer_0(iid, ENOMEM);
     765                fun_del_ref(fun);
     766                return;
     767        }
     768
     769        fibril_rwlock_read_lock(&device_tree.rwlock);
     770
     771        /* Check function state */
     772        if (fun->state == FUN_REMOVED) {
     773                fibril_rwlock_read_unlock(&device_tree.rwlock);
     774                free(buffer);
     775
     776                async_answer_0(data_callid, ENOENT);
     777                async_answer_0(iid, ENOENT);
     778                fun_del_ref(fun);
    543779                return;
    544780        }
     
    552788        async_answer_0(iid, EOK);
    553789
     790        fibril_rwlock_read_unlock(&device_tree.rwlock);
     791        fun_del_ref(fun);
    554792        free(buffer);
    555793}
     
    571809        if (!async_data_read_receive(&data_callid, &data_len)) {
    572810                async_answer_0(iid, EINVAL);
     811                fun_del_ref(fun);
    573812                return;
    574813        }
     
    578817                async_answer_0(data_callid, ENOMEM);
    579818                async_answer_0(iid, ENOMEM);
    580                 return;
    581         }
    582 
     819                fun_del_ref(fun);
     820                return;
     821        }
     822       
     823        fibril_rwlock_read_lock(&device_tree.rwlock);
     824       
     825        /* Check function state */
     826        if (fun->state == FUN_REMOVED) {
     827                fibril_rwlock_read_unlock(&device_tree.rwlock);
     828                free(buffer);
     829
     830                async_answer_0(data_callid, ENOENT);
     831                async_answer_0(iid, ENOENT);
     832                fun_del_ref(fun);
     833                return;
     834        }
     835       
    583836        size_t sent_length = str_size(fun->pathname);
    584837        if (sent_length > data_len) {
     
    589842        async_answer_0(iid, EOK);
    590843
     844        fibril_rwlock_read_unlock(&device_tree.rwlock);
     845        fun_del_ref(fun);
    591846        free(buffer);
    592847}
     
    609864        dev_node_t *dev = find_dev_node_no_lock(&device_tree,
    610865            IPC_GET_ARG1(*icall));
    611         if (dev == NULL) {
     866        if (dev == NULL || dev->state == DEVICE_REMOVED) {
    612867                fibril_rwlock_read_unlock(&device_tree.rwlock);
    613868                async_answer_0(callid, ENOENT);
     
    648903        fibril_rwlock_read_lock(&device_tree.rwlock);
    649904       
     905        fun = find_fun_node_no_lock(&device_tree, IPC_GET_ARG1(*icall));
     906        if (fun == NULL || fun->state == FUN_REMOVED) {
     907                fibril_rwlock_read_unlock(&device_tree.rwlock);
     908                async_answer_0(iid, ENOENT);
     909                return;
     910        }
     911       
     912        if (fun->child == NULL) {
     913                fibril_rwlock_read_unlock(&device_tree.rwlock);
     914                async_answer_0(iid, ENOENT);
     915                return;
     916        }
     917       
     918        async_answer_1(iid, EOK, fun->child->handle);
     919       
     920        fibril_rwlock_read_unlock(&device_tree.rwlock);
     921}
     922
     923/** Online function.
     924 *
     925 * Send a request to online a function to the responsible driver.
     926 * The driver may offline other functions if necessary (i.e. if the state
     927 * of this function is linked to state of another function somehow).
     928 */
     929static void devman_fun_online(ipc_callid_t iid, ipc_call_t *icall)
     930{
     931        fun_node_t *fun;
     932        int rc;
     933
    650934        fun = find_fun_node(&device_tree, IPC_GET_ARG1(*icall));
    651935        if (fun == NULL) {
    652                 fibril_rwlock_read_unlock(&device_tree.rwlock);
    653                 async_answer_0(iid, ENOENT);
    654                 return;
    655         }
    656        
    657         if (fun->child == NULL) {
    658                 fibril_rwlock_read_unlock(&device_tree.rwlock);
    659                 async_answer_0(iid, ENOENT);
    660                 return;
    661         }
    662        
    663         async_answer_1(iid, EOK, fun->child->handle);
    664        
    665         fibril_rwlock_read_unlock(&device_tree.rwlock);
     936                async_answer_0(iid, ENOENT);
     937                return;
     938        }
     939       
     940        rc = driver_fun_online(&device_tree, fun);
     941        fun_del_ref(fun);
     942       
     943        async_answer_0(iid, (sysarg_t) rc);
     944}
     945
     946/** Offline function.
     947 *
     948 * Send a request to offline a function to the responsible driver. As
     949 * a result the subtree rooted at that function should be cleanly
     950 * detatched. The driver may offline other functions if necessary
     951 * (i.e. if the state of this function is linked to state of another
     952 * function somehow).
     953 */
     954static void devman_fun_offline(ipc_callid_t iid, ipc_call_t *icall)
     955{
     956        fun_node_t *fun;
     957        int rc;
     958
     959        fun = find_fun_node(&device_tree, IPC_GET_ARG1(*icall));
     960        if (fun == NULL) {
     961                async_answer_0(iid, ENOENT);
     962                return;
     963        }
     964       
     965        rc = driver_fun_offline(&device_tree, fun);
     966        fun_del_ref(fun);
     967       
     968        async_answer_0(iid, (sysarg_t) rc);
    666969}
    667970
     
    678981        }
    679982
     983        fibril_rwlock_read_lock(&device_tree.rwlock);
     984
     985        /* Check function state */
     986        if (fun->state == FUN_REMOVED) {
     987                fibril_rwlock_read_unlock(&device_tree.rwlock);
     988                async_answer_0(iid, ENOENT);
     989                return;
     990        }
     991
    680992        async_answer_1(iid, EOK, fun->handle);
     993        fibril_rwlock_read_unlock(&device_tree.rwlock);
     994        fun_del_ref(fun);
    681995}
    682996
     
    7101024                        devman_fun_get_path(callid, &call);
    7111025                        break;
     1026                case DEVMAN_FUN_ONLINE:
     1027                        devman_fun_online(callid, &call);
     1028                        break;
     1029                case DEVMAN_FUN_OFFLINE:
     1030                        devman_fun_offline(callid, &call);
     1031                        break;
    7121032                case DEVMAN_FUN_SID_TO_HANDLE:
    7131033                        devman_fun_sid_to_handle(callid, &call);
     
    7301050        if (fun == NULL)
    7311051                dev = find_dev_node(&device_tree, handle);
    732         else
     1052        else {
     1053                fibril_rwlock_read_lock(&device_tree.rwlock);
    7331054                dev = fun->dev;
     1055                if (dev != NULL)
     1056                        dev_add_ref(dev);
     1057                fibril_rwlock_read_unlock(&device_tree.rwlock);
     1058        }
    7341059
    7351060        /*
     
    7431068                    "function with handle %" PRIun " was found.", handle);
    7441069                async_answer_0(iid, ENOENT);
    745                 return;
     1070                goto cleanup;
    7461071        }
    7471072
     
    7511076                    handle);
    7521077                async_answer_0(iid, ENOENT);
    753                 return;
     1078                goto cleanup;
    7541079        }
    7551080       
    7561081        driver_t *driver = NULL;
     1082       
     1083        fibril_rwlock_read_lock(&device_tree.rwlock);
    7571084       
    7581085        if (drv_to_parent) {
     
    7691096        }
    7701097       
     1098        fibril_rwlock_read_unlock(&device_tree.rwlock);
     1099       
    7711100        if (driver == NULL) {
    7721101                log_msg(LVL_ERROR, "IPC forwarding refused - " \
    7731102                    "the device %" PRIun " is not in usable state.", handle);
    7741103                async_answer_0(iid, ENOENT);
    775                 return;
     1104                goto cleanup;
    7761105        }
    7771106       
     
    7861115                    "Could not forward to driver `%s'.", driver->name);
    7871116                async_answer_0(iid, EINVAL);
    788                 return;
     1117                goto cleanup;
    7891118        }
    7901119
     
    8021131        async_forward_fast(iid, exch, method, fwd_h, 0, IPC_FF_NONE);
    8031132        async_exchange_end(exch);
     1133
     1134cleanup:
     1135        if (dev != NULL)
     1136                dev_del_ref(dev);
     1137        if (fun != NULL)
     1138                fun_del_ref(fun);
    8041139}
    8051140
     
    8111146        fun_node_t *fun;
    8121147        dev_node_t *dev;
     1148        devman_handle_t handle;
     1149        driver_t *driver;
    8131150
    8141151        fun = find_loc_tree_function(&device_tree, service_id);
    8151152       
    816         if (fun == NULL || fun->dev->drv == NULL) {
     1153        fibril_rwlock_read_lock(&device_tree.rwlock);
     1154       
     1155        if (fun == NULL || fun->dev == NULL || fun->dev->drv == NULL) {
    8171156                log_msg(LVL_WARN, "devman_connection_loc(): function "
    8181157                    "not found.\n");
     1158                fibril_rwlock_read_unlock(&device_tree.rwlock);
    8191159                async_answer_0(iid, ENOENT);
    8201160                return;
     
    8221162       
    8231163        dev = fun->dev;
    824        
    825         async_exch_t *exch = async_exchange_begin(dev->drv->sess);
    826         async_forward_fast(iid, exch, DRIVER_CLIENT, fun->handle, 0,
     1164        driver = dev->drv;
     1165        handle = fun->handle;
     1166       
     1167        fibril_rwlock_read_unlock(&device_tree.rwlock);
     1168       
     1169        async_exch_t *exch = async_exchange_begin(driver->sess);
     1170        async_forward_fast(iid, exch, DRIVER_CLIENT, handle, 0,
    8271171            IPC_FF_NONE);
    8281172        async_exchange_end(exch);
     
    8301174        log_msg(LVL_DEBUG,
    8311175            "Forwarding loc service request for `%s' function to driver `%s'.",
    832             fun->pathname, dev->drv->name);
     1176            fun->pathname, driver->name);
     1177
     1178        fun_del_ref(fun);
    8331179}
    8341180
Note: See TracChangeset for help on using the changeset viewer.