Changeset 02e5e34 in mainline for uspace/srv/devman/fun.c
- Timestamp:
- 2013-09-10T21:27:30Z (11 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- a501e22c
- Parents:
- 181c32f
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/devman/fun.c
r181c32f r02e5e34 33 33 #include <errno.h> 34 34 #include <io/log.h> 35 35 #include <loc.h> 36 37 #include "dev.h" 36 38 #include "devman.h" 39 #include "devtree.h" 40 #include "driver.h" 37 41 #include "fun.h" 42 #include "main.h" 43 #include "loc.h" 38 44 39 45 static fun_node_t *find_node_child(dev_tree_t *, fun_node_t *, const char *); … … 280 286 } 281 287 288 static 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 298 int 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 355 int 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 282 430 /** @} 283 431 */
Note:
See TracChangeset
for help on using the changeset viewer.