Changeset 00aece0 in mainline for uspace/srv/devman/main.c
- Timestamp:
- 2012-02-18T16:47:38Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 4449c6c
- Parents:
- bd5f3b7 (diff), f943dd3 (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. - File:
-
- 1 edited
-
uspace/srv/devman/main.c (modified) (33 diffs)
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/devman/main.c
rbd5f3b7 r00aece0 234 234 dev_node_t *dev_node = (dev_node_t *) arg; 235 235 assign_driver(dev_node, &drivers_list, &device_tree); 236 237 /* Delete one reference we got from the caller. */ 238 dev_del_ref(dev_node); 236 239 return EOK; 237 240 } 238 241 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) { 242 static 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) { 301 256 dev = create_dev_node(); 302 257 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; 307 260 } 308 261 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 } 313 265 314 266 log_msg(LVL_DEBUG, "devman_add_function(fun=\"%s\")", fun->pathname); 315 267 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; 319 270 assert(dev != NULL); 271 272 /* Give one reference over to assign_driver_fibril(). */ 273 dev_add_ref(dev); 320 274 /* 321 275 * Try to find a suitable driver and assign it to the device. We do … … 327 281 fid_t assign_fibril = fibril_create(assign_driver_fibril, dev); 328 282 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 299 static 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 device_state_t dev_state; 319 320 dev_add_ref(dev); 321 dev_state = dev->state; 322 323 fibril_rwlock_write_unlock(&device_tree.rwlock); 324 325 /* If device is owned by driver, ask driver to give it up. */ 326 if (dev_state == DEVICE_USABLE) { 327 rc = driver_dev_remove(&device_tree, dev); 328 if (rc != EOK) { 329 dev_del_ref(dev); 330 return ENOTSUP; 331 } 332 } 333 334 /* Verify that driver removed all functions */ 335 fibril_rwlock_read_lock(&device_tree.rwlock); 336 if (!list_empty(&dev->functions)) { 337 fibril_rwlock_read_unlock(&device_tree.rwlock); 338 dev_del_ref(dev); 339 return EIO; 340 } 341 342 driver_t *driver = dev->drv; 343 fibril_rwlock_read_unlock(&device_tree.rwlock); 344 345 if (driver) 346 detach_driver(&device_tree, dev); 347 348 fibril_rwlock_write_lock(&device_tree.rwlock); 349 remove_dev_node(&device_tree, dev); 350 351 /* Delete ref created when node was inserted */ 352 dev_del_ref(dev); 353 /* Delete ref created by dev_add_ref(dev) above */ 354 dev_del_ref(dev); 336 355 } 337 356 } else { 338 loc_register_tree_function(fun, tree); 357 /* Unregister from location service */ 358 rc = loc_service_unregister(fun->service_id); 359 if (rc != EOK) { 360 fibril_rwlock_write_unlock(&device_tree.rwlock); 361 log_msg(LVL_ERROR, "Failed unregistering tree service."); 362 return EIO; 363 } 364 365 fun->service_id = 0; 366 } 367 368 fun->state = FUN_OFF_LINE; 369 fibril_rwlock_write_unlock(&device_tree.rwlock); 370 371 return EOK; 372 } 373 374 /** Handle function registration. 375 * 376 * Child devices are registered by their parent's device driver. 377 */ 378 static void devman_add_function(ipc_callid_t callid, ipc_call_t *call) 379 { 380 fun_type_t ftype = (fun_type_t) IPC_GET_ARG1(*call); 381 devman_handle_t dev_handle = IPC_GET_ARG2(*call); 382 sysarg_t match_count = IPC_GET_ARG3(*call); 383 dev_tree_t *tree = &device_tree; 384 385 dev_node_t *pdev = find_dev_node(&device_tree, dev_handle); 386 if (pdev == NULL) { 387 async_answer_0(callid, ENOENT); 388 return; 389 } 390 391 if (ftype != fun_inner && ftype != fun_exposed) { 392 /* Unknown function type */ 393 log_msg(LVL_ERROR, 394 "Unknown function type %d provided by driver.", 395 (int) ftype); 396 397 dev_del_ref(pdev); 398 async_answer_0(callid, EINVAL); 399 return; 400 } 401 402 char *fun_name = NULL; 403 int rc = async_data_write_accept((void **)&fun_name, true, 0, 0, 0, 0); 404 if (rc != EOK) { 405 dev_del_ref(pdev); 406 async_answer_0(callid, rc); 407 return; 408 } 409 410 fibril_rwlock_write_lock(&tree->rwlock); 411 412 /* Check device state */ 413 if (pdev->state == DEVICE_REMOVED) { 414 fibril_rwlock_write_unlock(&tree->rwlock); 415 dev_del_ref(pdev); 416 async_answer_0(callid, ENOENT); 417 return; 418 } 419 420 /* Check that function with same name is not there already. */ 421 if (find_fun_node_in_device(tree, pdev, fun_name) != NULL) { 422 fibril_rwlock_write_unlock(&tree->rwlock); 423 dev_del_ref(pdev); 424 async_answer_0(callid, EEXISTS); 425 printf(NAME ": Warning, driver tried to register `%s' twice.\n", 426 fun_name); 427 free(fun_name); 428 return; 429 } 430 431 fun_node_t *fun = create_fun_node(); 432 fun_add_ref(fun); 433 fun->ftype = ftype; 434 435 if (!insert_fun_node(&device_tree, fun, fun_name, pdev)) { 436 fibril_rwlock_write_unlock(&tree->rwlock); 437 dev_del_ref(pdev); 438 delete_fun_node(fun); 439 async_answer_0(callid, ENOMEM); 440 return; 441 } 442 443 fibril_rwlock_write_unlock(&tree->rwlock); 444 dev_del_ref(pdev); 445 446 devman_receive_match_ids(match_count, &fun->match_ids); 447 448 rc = online_function(fun); 449 if (rc != EOK) { 450 /* XXX clean up */ 451 async_answer_0(callid, rc); 452 return; 339 453 } 340 454 … … 356 470 async_answer_0(callid, rc); 357 471 return; 358 } 472 } 359 473 360 474 fun_node_t *fun = find_fun_node(&device_tree, handle); … … 364 478 } 365 479 480 fibril_rwlock_read_lock(&device_tree.rwlock); 481 482 /* Check function state */ 483 if (fun->state == FUN_REMOVED) { 484 fibril_rwlock_read_unlock(&device_tree.rwlock); 485 async_answer_0(callid, ENOENT); 486 return; 487 } 488 366 489 rc = loc_category_get_id(cat_name, &cat_id, IPC_FLAG_BLOCKING); 367 490 if (rc == EOK) { 368 491 loc_service_add_to_cat(fun->service_id, cat_id); 492 log_msg(LVL_NOTE, "Function `%s' added to category `%s'.", 493 fun->pathname, cat_name); 369 494 } else { 370 495 log_msg(LVL_ERROR, "Failed adding function `%s' to category " … … 372 497 } 373 498 374 log_msg(LVL_NOTE, "Function `%s' added to category `%s'.", 375 fun->pathname, cat_name); 376 377 async_answer_0(callid, EOK); 499 fibril_rwlock_read_unlock(&device_tree.rwlock); 500 fun_del_ref(fun); 501 502 async_answer_0(callid, rc); 503 } 504 505 /** Online function by driver request. 506 * 507 */ 508 static void devman_drv_fun_online(ipc_callid_t iid, ipc_call_t *icall, 509 driver_t *drv) 510 { 511 fun_node_t *fun; 512 int rc; 513 514 log_msg(LVL_DEBUG, "devman_drv_fun_online()"); 515 516 fun = find_fun_node(&device_tree, IPC_GET_ARG1(*icall)); 517 if (fun == NULL) { 518 async_answer_0(iid, ENOENT); 519 return; 520 } 521 522 fibril_rwlock_read_lock(&device_tree.rwlock); 523 if (fun->dev == NULL || fun->dev->drv != drv) { 524 fibril_rwlock_read_unlock(&device_tree.rwlock); 525 fun_del_ref(fun); 526 async_answer_0(iid, ENOENT); 527 return; 528 } 529 fibril_rwlock_read_unlock(&device_tree.rwlock); 530 531 rc = online_function(fun); 532 if (rc != EOK) { 533 fun_del_ref(fun); 534 async_answer_0(iid, (sysarg_t) rc); 535 return; 536 } 537 538 fun_del_ref(fun); 539 540 async_answer_0(iid, (sysarg_t) EOK); 541 } 542 543 544 /** Offline function by driver request. 545 * 546 */ 547 static void devman_drv_fun_offline(ipc_callid_t iid, ipc_call_t *icall, 548 driver_t *drv) 549 { 550 fun_node_t *fun; 551 int rc; 552 553 fun = find_fun_node(&device_tree, IPC_GET_ARG1(*icall)); 554 if (fun == NULL) { 555 async_answer_0(iid, ENOENT); 556 return; 557 } 558 559 fibril_rwlock_write_lock(&device_tree.rwlock); 560 if (fun->dev == NULL || fun->dev->drv != drv) { 561 fun_del_ref(fun); 562 async_answer_0(iid, ENOENT); 563 return; 564 } 565 fibril_rwlock_write_unlock(&device_tree.rwlock); 566 567 rc = offline_function(fun); 568 if (rc != EOK) { 569 fun_del_ref(fun); 570 async_answer_0(iid, (sysarg_t) rc); 571 return; 572 } 573 574 fun_del_ref(fun); 575 async_answer_0(iid, (sysarg_t) EOK); 378 576 } 379 577 … … 385 583 int rc; 386 584 585 fun_node_t *fun = find_fun_node(&device_tree, fun_handle); 586 if (fun == NULL) { 587 async_answer_0(callid, ENOENT); 588 return; 589 } 590 387 591 fibril_rwlock_write_lock(&tree->rwlock); 388 592 389 fun_node_t *fun = find_fun_node_no_lock(&device_tree, fun_handle); 390 if (fun == NULL) { 593 log_msg(LVL_DEBUG, "devman_remove_function(fun='%s')", fun->pathname); 594 595 /* Check function state */ 596 if (fun->state == FUN_REMOVED) { 391 597 fibril_rwlock_write_unlock(&tree->rwlock); 392 598 async_answer_0(callid, ENOENT); … … 394 600 } 395 601 396 log_msg(LVL_DEBUG, "devman_remove_function(fun='%s')", fun->pathname);397 398 602 if (fun->ftype == fun_inner) { 399 /* Handle possible descendants */ 400 /* TODO */ 401 log_msg(LVL_WARN, "devman_remove_function(): not handling " 402 "descendants\n"); 603 /* This is a surprise removal. Handle possible descendants */ 604 if (fun->child != NULL) { 605 dev_node_t *dev = fun->child; 606 device_state_t dev_state; 607 int gone_rc; 608 609 dev_add_ref(dev); 610 dev_state = dev->state; 611 612 fibril_rwlock_write_unlock(&device_tree.rwlock); 613 614 /* If device is owned by driver, inform driver it is gone. */ 615 if (dev_state == DEVICE_USABLE) 616 gone_rc = driver_dev_gone(&device_tree, dev); 617 else 618 gone_rc = EOK; 619 620 fibril_rwlock_read_lock(&device_tree.rwlock); 621 622 /* Verify that driver succeeded and removed all functions */ 623 if (gone_rc != EOK || !list_empty(&dev->functions)) { 624 log_msg(LVL_ERROR, "Driver did not remove " 625 "functions for device that is gone. " 626 "Device node is now defunct."); 627 628 /* 629 * Not much we can do but mark the device 630 * node as having invalid state. This 631 * is a driver bug. 632 */ 633 dev->state = DEVICE_INVALID; 634 fibril_rwlock_read_unlock(&device_tree.rwlock); 635 dev_del_ref(dev); 636 if (gone_rc == EOK) 637 gone_rc = ENOTSUP; 638 async_answer_0(callid, gone_rc); 639 return; 640 } 641 642 driver_t *driver = dev->drv; 643 fibril_rwlock_read_unlock(&device_tree.rwlock); 644 645 if (driver) 646 detach_driver(&device_tree, dev); 647 648 fibril_rwlock_write_lock(&device_tree.rwlock); 649 remove_dev_node(&device_tree, dev); 650 651 /* Delete ref created when node was inserted */ 652 dev_del_ref(dev); 653 /* Delete ref created by dev_add_ref(dev) above */ 654 dev_del_ref(dev); 655 } 403 656 } 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; 657 if (fun->service_id != 0) { 658 /* Unregister from location service */ 659 rc = loc_service_unregister(fun->service_id); 660 if (rc != EOK) { 661 log_msg(LVL_ERROR, "Failed unregistering tree " 662 "service."); 663 fibril_rwlock_write_unlock(&tree->rwlock); 664 fun_del_ref(fun); 665 async_answer_0(callid, EIO); 666 return; 667 } 411 668 } 412 669 } … … 414 671 remove_fun_node(&device_tree, fun); 415 672 fibril_rwlock_write_unlock(&tree->rwlock); 416 delete_fun_node(fun); 673 674 /* Delete ref added when inserting function into tree */ 675 fun_del_ref(fun); 676 /* Delete ref added above when looking up function */ 677 fun_del_ref(fun); 417 678 418 679 log_msg(LVL_DEBUG, "devman_remove_function() succeeded."); … … 485 746 devman_add_function_to_cat(callid, &call); 486 747 break; 748 case DEVMAN_DRV_FUN_ONLINE: 749 devman_drv_fun_online(callid, &call, driver); 750 break; 751 case DEVMAN_DRV_FUN_OFFLINE: 752 devman_drv_fun_offline(callid, &call, driver); 753 break; 487 754 case DEVMAN_REMOVE_FUNCTION: 488 755 devman_remove_function(callid, &call); 489 756 break; 490 757 default: 491 async_answer_0(callid, EINVAL); 758 async_answer_0(callid, EINVAL); 492 759 break; 493 760 } … … 500 767 { 501 768 char *pathname; 769 devman_handle_t handle; 502 770 503 771 int rc = async_data_write_accept((void **) &pathname, true, 0, 0, 0, 0); … … 516 784 } 517 785 518 async_answer_1(iid, EOK, fun->handle); 786 fibril_rwlock_read_lock(&device_tree.rwlock); 787 788 /* Check function state */ 789 if (fun->state == FUN_REMOVED) { 790 fibril_rwlock_read_unlock(&device_tree.rwlock); 791 async_answer_0(iid, ENOENT); 792 return; 793 } 794 handle = fun->handle; 795 796 fibril_rwlock_read_unlock(&device_tree.rwlock); 797 798 /* Delete reference created above by find_fun_node_by_path() */ 799 fun_del_ref(fun); 800 801 async_answer_1(iid, EOK, handle); 519 802 } 520 803 … … 534 817 if (!async_data_read_receive(&data_callid, &data_len)) { 535 818 async_answer_0(iid, EINVAL); 819 fun_del_ref(fun); 536 820 return; 537 821 } … … 541 825 async_answer_0(data_callid, ENOMEM); 542 826 async_answer_0(iid, ENOMEM); 827 fun_del_ref(fun); 828 return; 829 } 830 831 fibril_rwlock_read_lock(&device_tree.rwlock); 832 833 /* Check function state */ 834 if (fun->state == FUN_REMOVED) { 835 fibril_rwlock_read_unlock(&device_tree.rwlock); 836 free(buffer); 837 838 async_answer_0(data_callid, ENOENT); 839 async_answer_0(iid, ENOENT); 840 fun_del_ref(fun); 543 841 return; 544 842 } … … 552 850 async_answer_0(iid, EOK); 553 851 852 fibril_rwlock_read_unlock(&device_tree.rwlock); 853 fun_del_ref(fun); 554 854 free(buffer); 555 855 } … … 571 871 if (!async_data_read_receive(&data_callid, &data_len)) { 572 872 async_answer_0(iid, EINVAL); 873 fun_del_ref(fun); 573 874 return; 574 875 } … … 578 879 async_answer_0(data_callid, ENOMEM); 579 880 async_answer_0(iid, ENOMEM); 580 return; 581 } 582 881 fun_del_ref(fun); 882 return; 883 } 884 885 fibril_rwlock_read_lock(&device_tree.rwlock); 886 887 /* Check function state */ 888 if (fun->state == FUN_REMOVED) { 889 fibril_rwlock_read_unlock(&device_tree.rwlock); 890 free(buffer); 891 892 async_answer_0(data_callid, ENOENT); 893 async_answer_0(iid, ENOENT); 894 fun_del_ref(fun); 895 return; 896 } 897 583 898 size_t sent_length = str_size(fun->pathname); 584 899 if (sent_length > data_len) { … … 589 904 async_answer_0(iid, EOK); 590 905 906 fibril_rwlock_read_unlock(&device_tree.rwlock); 907 fun_del_ref(fun); 591 908 free(buffer); 592 909 } … … 609 926 dev_node_t *dev = find_dev_node_no_lock(&device_tree, 610 927 IPC_GET_ARG1(*icall)); 611 if (dev == NULL ) {928 if (dev == NULL || dev->state == DEVICE_REMOVED) { 612 929 fibril_rwlock_read_unlock(&device_tree.rwlock); 613 930 async_answer_0(callid, ENOENT); … … 648 965 fibril_rwlock_read_lock(&device_tree.rwlock); 649 966 967 fun = find_fun_node_no_lock(&device_tree, IPC_GET_ARG1(*icall)); 968 if (fun == NULL || fun->state == FUN_REMOVED) { 969 fibril_rwlock_read_unlock(&device_tree.rwlock); 970 async_answer_0(iid, ENOENT); 971 return; 972 } 973 974 if (fun->child == NULL) { 975 fibril_rwlock_read_unlock(&device_tree.rwlock); 976 async_answer_0(iid, ENOENT); 977 return; 978 } 979 980 async_answer_1(iid, EOK, fun->child->handle); 981 982 fibril_rwlock_read_unlock(&device_tree.rwlock); 983 } 984 985 /** Online function. 986 * 987 * Send a request to online a function to the responsible driver. 988 * The driver may offline other functions if necessary (i.e. if the state 989 * of this function is linked to state of another function somehow). 990 */ 991 static void devman_fun_online(ipc_callid_t iid, ipc_call_t *icall) 992 { 993 fun_node_t *fun; 994 int rc; 995 650 996 fun = find_fun_node(&device_tree, IPC_GET_ARG1(*icall)); 651 997 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); 998 async_answer_0(iid, ENOENT); 999 return; 1000 } 1001 1002 rc = driver_fun_online(&device_tree, fun); 1003 fun_del_ref(fun); 1004 1005 async_answer_0(iid, (sysarg_t) rc); 1006 } 1007 1008 /** Offline function. 1009 * 1010 * Send a request to offline a function to the responsible driver. As 1011 * a result the subtree rooted at that function should be cleanly 1012 * detatched. The driver may offline other functions if necessary 1013 * (i.e. if the state of this function is linked to state of another 1014 * function somehow). 1015 */ 1016 static void devman_fun_offline(ipc_callid_t iid, ipc_call_t *icall) 1017 { 1018 fun_node_t *fun; 1019 int rc; 1020 1021 fun = find_fun_node(&device_tree, IPC_GET_ARG1(*icall)); 1022 if (fun == NULL) { 1023 async_answer_0(iid, ENOENT); 1024 return; 1025 } 1026 1027 rc = driver_fun_offline(&device_tree, fun); 1028 fun_del_ref(fun); 1029 1030 async_answer_0(iid, (sysarg_t) rc); 666 1031 } 667 1032 … … 678 1043 } 679 1044 1045 fibril_rwlock_read_lock(&device_tree.rwlock); 1046 1047 /* Check function state */ 1048 if (fun->state == FUN_REMOVED) { 1049 fibril_rwlock_read_unlock(&device_tree.rwlock); 1050 async_answer_0(iid, ENOENT); 1051 return; 1052 } 1053 680 1054 async_answer_1(iid, EOK, fun->handle); 1055 fibril_rwlock_read_unlock(&device_tree.rwlock); 1056 fun_del_ref(fun); 681 1057 } 682 1058 … … 710 1086 devman_fun_get_path(callid, &call); 711 1087 break; 1088 case DEVMAN_FUN_ONLINE: 1089 devman_fun_online(callid, &call); 1090 break; 1091 case DEVMAN_FUN_OFFLINE: 1092 devman_fun_offline(callid, &call); 1093 break; 712 1094 case DEVMAN_FUN_SID_TO_HANDLE: 713 1095 devman_fun_sid_to_handle(callid, &call); … … 730 1112 if (fun == NULL) 731 1113 dev = find_dev_node(&device_tree, handle); 732 else 1114 else { 1115 fibril_rwlock_read_lock(&device_tree.rwlock); 733 1116 dev = fun->dev; 1117 if (dev != NULL) 1118 dev_add_ref(dev); 1119 fibril_rwlock_read_unlock(&device_tree.rwlock); 1120 } 734 1121 735 1122 /* … … 743 1130 "function with handle %" PRIun " was found.", handle); 744 1131 async_answer_0(iid, ENOENT); 745 return;1132 goto cleanup; 746 1133 } 747 1134 … … 751 1138 handle); 752 1139 async_answer_0(iid, ENOENT); 753 return;1140 goto cleanup; 754 1141 } 755 1142 756 1143 driver_t *driver = NULL; 1144 1145 fibril_rwlock_read_lock(&device_tree.rwlock); 757 1146 758 1147 if (drv_to_parent) { … … 769 1158 } 770 1159 1160 fibril_rwlock_read_unlock(&device_tree.rwlock); 1161 771 1162 if (driver == NULL) { 772 1163 log_msg(LVL_ERROR, "IPC forwarding refused - " \ 773 1164 "the device %" PRIun " is not in usable state.", handle); 774 1165 async_answer_0(iid, ENOENT); 775 return;1166 goto cleanup; 776 1167 } 777 1168 … … 786 1177 "Could not forward to driver `%s'.", driver->name); 787 1178 async_answer_0(iid, EINVAL); 788 return;1179 goto cleanup; 789 1180 } 790 1181 … … 802 1193 async_forward_fast(iid, exch, method, fwd_h, 0, IPC_FF_NONE); 803 1194 async_exchange_end(exch); 1195 1196 cleanup: 1197 if (dev != NULL) 1198 dev_del_ref(dev); 1199 if (fun != NULL) 1200 fun_del_ref(fun); 804 1201 } 805 1202 … … 811 1208 fun_node_t *fun; 812 1209 dev_node_t *dev; 1210 devman_handle_t handle; 1211 driver_t *driver; 813 1212 814 1213 fun = find_loc_tree_function(&device_tree, service_id); 815 1214 816 if (fun == NULL || fun->dev->drv == NULL) { 1215 fibril_rwlock_read_lock(&device_tree.rwlock); 1216 1217 if (fun == NULL || fun->dev == NULL || fun->dev->drv == NULL) { 817 1218 log_msg(LVL_WARN, "devman_connection_loc(): function " 818 1219 "not found.\n"); 1220 fibril_rwlock_read_unlock(&device_tree.rwlock); 819 1221 async_answer_0(iid, ENOENT); 820 1222 return; … … 822 1224 823 1225 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, 1226 driver = dev->drv; 1227 handle = fun->handle; 1228 1229 fibril_rwlock_read_unlock(&device_tree.rwlock); 1230 1231 async_exch_t *exch = async_exchange_begin(driver->sess); 1232 async_forward_fast(iid, exch, DRIVER_CLIENT, handle, 0, 827 1233 IPC_FF_NONE); 828 1234 async_exchange_end(exch); … … 830 1236 log_msg(LVL_DEBUG, 831 1237 "Forwarding loc service request for `%s' function to driver `%s'.", 832 fun->pathname, dev->drv->name); 1238 fun->pathname, driver->name); 1239 1240 fun_del_ref(fun); 833 1241 } 834 1242 … … 901 1309 902 1310 /* 903 * !!! devman_connection ... as the device manager is not a real loc 904 * driver (it uses a completely different ipc protocol than an ordinary 905 * loc driver) forwarding a connection from client to the devman by 906 * location service would not work. 1311 * Caution: As the device manager is not a real loc 1312 * driver (it uses a completely different IPC protocol 1313 * than an ordinary loc driver), forwarding a connection 1314 * from client to the devman by location service will 1315 * not work. 907 1316 */ 908 loc_server_register(NAME , devman_connection);1317 loc_server_register(NAME); 909 1318 910 1319 return true; … … 917 1326 if (log_init(NAME, LVL_WARN) != EOK) { 918 1327 printf(NAME ": Error initializing logging subsystem.\n"); 919 return -1;920 }921 922 if (!devman_init()) {923 log_msg(LVL_ERROR, "Error while initializing service.");924 1328 return -1; 925 1329 } … … 930 1334 async_set_client_connection(devman_connection); 931 1335 1336 if (!devman_init()) { 1337 log_msg(LVL_ERROR, "Error while initializing service."); 1338 return -1; 1339 } 1340 932 1341 /* Register device manager at naming service. */ 933 1342 if (service_register(SERVICE_DEVMAN) != EOK) {
Note:
See TracChangeset
for help on using the changeset viewer.
