Changeset a1b7e80 in mainline
- Timestamp:
- 2011-09-02T16:54:18Z (13 years ago)
- 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. - Location:
- uspace
- Files:
-
- 24 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/devctl/devctl.c
r7a72ce1a ra1b7e80 37 37 #include <stdio.h> 38 38 #include <stdlib.h> 39 #include <str_error.h> 39 40 #include <sys/typefmt.h> 40 41 … … 43 44 #define MAX_NAME_LENGTH 1024 44 45 45 static int fun_ tree_print(devman_handle_t funh, int lvl)46 static int fun_subtree_print(devman_handle_t funh, int lvl) 46 47 { 47 48 char name[MAX_NAME_LENGTH]; … … 84 85 85 86 for (i = 0; i < count; i++) 86 fun_ tree_print(cfuns[i], lvl + 1);87 fun_subtree_print(cfuns[i], lvl + 1); 87 88 88 89 free(cfuns); … … 90 91 } 91 92 92 int main(int argc, char *argv[])93 static int fun_tree_print(void) 93 94 { 94 95 devman_handle_t root_fun; … … 98 99 if (rc != EOK) { 99 100 printf(NAME ": Error resolving root function.\n"); 101 return EIO; 102 } 103 104 rc = fun_subtree_print(root_fun, 0); 105 if (rc != EOK) 106 return EIO; 107 108 return EOK; 109 } 110 111 static int fun_online(const char *path) 112 { 113 devman_handle_t funh; 114 int rc; 115 116 rc = devman_fun_get_handle(path, &funh, 0); 117 if (rc != EOK) { 118 printf(NAME ": Error resolving device function '%s' (%s)\n", 119 path, str_error(rc)); 120 return rc; 121 } 122 123 rc = devman_fun_online(funh); 124 if (rc != EOK) { 125 printf(NAME ": Failed to online function '%s'.\n", path); 126 return rc; 127 } 128 129 return EOK; 130 } 131 132 static int fun_offline(const char *path) 133 { 134 devman_handle_t funh; 135 int rc; 136 137 rc = devman_fun_get_handle(path, &funh, 0); 138 if (rc != EOK) { 139 printf(NAME ": Error resolving device function '%s' (%s)\n", 140 path, str_error(rc)); 141 return rc; 142 } 143 144 rc = devman_fun_offline(funh); 145 if (rc != EOK) { 146 printf(NAME ": Failed to offline function '%s'.\n", path); 147 return rc; 148 } 149 150 return EOK; 151 } 152 153 static void print_syntax(void) 154 { 155 printf("syntax: devctl [(online|offline) <function>]\n"); 156 } 157 158 int main(int argc, char *argv[]) 159 { 160 int rc; 161 162 if (argc == 1) { 163 rc = fun_tree_print(); 164 if (rc != EOK) 165 return 2; 166 } else if (str_cmp(argv[1], "online") == 0) { 167 if (argc < 3) { 168 printf(NAME ": Argument missing.\n"); 169 print_syntax(); 170 return 1; 171 } 172 173 rc = fun_online(argv[2]); 174 if (rc != EOK) { 175 return 2; 176 } 177 } else if (str_cmp(argv[1], "offline") == 0) { 178 if (argc < 3) { 179 printf(NAME ": Argument missing.\n"); 180 print_syntax(); 181 return 1; 182 } 183 184 rc = fun_offline(argv[2]); 185 if (rc != EOK) { 186 return 2; 187 } 188 } else { 189 printf(NAME ": Invalid argument '%s'.\n", argv[1]); 190 print_syntax(); 100 191 return 1; 101 192 } 102 103 rc = fun_tree_print(root_fun, 0);104 if (rc != EOK)105 return 1;106 193 107 194 return 0; -
uspace/drv/bus/pci/pciintel/pci.c
r7a72ce1a ra1b7e80 215 215 }; 216 216 217 static pci_bus_t *pci_bus_new(void)218 {219 pci_bus_t *bus;220 221 bus = (pci_bus_t *) calloc(1, sizeof(pci_bus_t));222 if (bus == NULL)223 return NULL;224 225 fibril_mutex_initialize(&bus->conf_mutex);226 return bus;227 }228 229 static void pci_bus_delete(pci_bus_t *bus)230 {231 assert(bus != NULL);232 free(bus);233 }234 235 217 static void pci_conf_read(pci_fun_t *fun, int reg, uint8_t *buf, size_t len) 236 218 { … … 584 566 dnode->parent_sess = NULL; 585 567 586 bus = pci_bus_new();568 bus = ddf_dev_data_alloc(dnode, sizeof(pci_bus_t)); 587 569 if (bus == NULL) { 588 570 ddf_msg(LVL_ERROR, "pci_add_device allocation failed."); … … 590 572 goto fail; 591 573 } 574 fibril_mutex_initialize(&bus->conf_mutex); 575 592 576 bus->dnode = dnode; 593 577 dnode->driver_data = bus; … … 655 639 656 640 fail: 657 if (bus != NULL)658 pci_bus_delete(bus);659 660 641 if (dnode->parent_sess) 661 642 async_hangup(dnode->parent_sess); -
uspace/drv/bus/usb/uhci/uhci.c
r7a72ce1a ra1b7e80 192 192 ddf_fun_destroy(instance->rh_fun); \ 193 193 } \ 194 free(instance); \195 194 device->driver_data = NULL; \ 196 195 usb_log_error(message); \ -
uspace/drv/bus/usb/usbhid/kbd/kbddev.c
r7a72ce1a ra1b7e80 734 734 int rc = usb_kbd_create_function(hid_dev, kbd_dev); 735 735 if (rc != EOK) { 736 usb_kbd_ free(&kbd_dev);736 usb_kbd_destroy(kbd_dev); 737 737 return rc; 738 738 } … … 779 779 * @param kbd_dev Pointer to the structure to be destroyed. 780 780 */ 781 void usb_kbd_ free(usb_kbd_t **kbd_dev)782 { 783 if (kbd_dev == NULL || *kbd_dev == NULL) {781 void usb_kbd_destroy(usb_kbd_t *kbd_dev) 782 { 783 if (kbd_dev == NULL) { 784 784 return; 785 785 } 786 786 787 787 // hangup phone to the console 788 async_obsolete_hangup( (*kbd_dev)->console_phone);789 790 if ( (*kbd_dev)->repeat_mtx != NULL) {788 async_obsolete_hangup(kbd_dev->console_phone); 789 790 if (kbd_dev->repeat_mtx != NULL) { 791 791 //assert(!fibril_mutex_is_locked((*kbd_dev)->repeat_mtx)); 792 792 // FIXME - the fibril_mutex_is_locked may not cause 793 793 // fibril scheduling 794 while (fibril_mutex_is_locked( (*kbd_dev)->repeat_mtx)) {}795 free( (*kbd_dev)->repeat_mtx);794 while (fibril_mutex_is_locked(kbd_dev->repeat_mtx)) {} 795 free(kbd_dev->repeat_mtx); 796 796 } 797 797 798 798 // free all buffers 799 if ((*kbd_dev)->keys != NULL) { 800 free((*kbd_dev)->keys); 801 } 802 if ((*kbd_dev)->keys_old != NULL) { 803 free((*kbd_dev)->keys_old); 804 } 805 if ((*kbd_dev)->led_data != NULL) { 806 free((*kbd_dev)->led_data); 807 } 808 if ((*kbd_dev)->led_path != NULL) { 809 usb_hid_report_path_free((*kbd_dev)->led_path); 810 } 811 if ((*kbd_dev)->output_buffer != NULL) { 812 usb_hid_report_output_free((*kbd_dev)->output_buffer); 813 } 814 815 free(*kbd_dev); 816 *kbd_dev = NULL; 799 if (kbd_dev->keys != NULL) { 800 free(kbd_dev->keys); 801 } 802 if (kbd_dev->keys_old != NULL) { 803 free(kbd_dev->keys_old); 804 } 805 if (kbd_dev->led_data != NULL) { 806 free(kbd_dev->led_data); 807 } 808 if (kbd_dev->led_path != NULL) { 809 usb_hid_report_path_free(kbd_dev->led_path); 810 } 811 if (kbd_dev->output_buffer != NULL) { 812 usb_hid_report_output_free(kbd_dev->output_buffer); 813 } 817 814 } 818 815 … … 830 827 usb_kbd_mark_unusable(kbd_dev); 831 828 } else { 832 usb_kbd_ free(&kbd_dev);829 usb_kbd_destroy(kbd_dev); 833 830 } 834 831 } -
uspace/drv/bus/usb/usbhid/kbd/kbddev.h
r7a72ce1a ra1b7e80 131 131 int usb_kbd_is_ready_to_destroy(const usb_kbd_t *kbd_dev); 132 132 133 void usb_kbd_ free(usb_kbd_t **kbd_dev);133 void usb_kbd_destroy(usb_kbd_t *kbd_dev); 134 134 135 135 void usb_kbd_push_ev(struct usb_hid_dev *hid_dev, usb_kbd_t *kbd_dev, -
uspace/drv/bus/usb/usbhid/kbd/kbdrepeat.c
r7a72ce1a ra1b7e80 80 80 if (!usb_kbd_is_initialized(kbd)) { 81 81 if (usb_kbd_is_ready_to_destroy(kbd)) { 82 usb_kbd_free(&kbd); 83 assert(kbd == NULL); 82 usb_kbd_destroy(kbd); 84 83 } 85 84 return; -
uspace/drv/bus/usb/usbhid/main.c
r7a72ce1a ra1b7e80 93 93 if (rc != EOK) { 94 94 usb_log_error("Failed to initialize USB/HID device.\n"); 95 usb_hid_ free(&hid_dev);95 usb_hid_destroy(hid_dev); 96 96 return rc; 97 97 } -
uspace/drv/bus/usb/usbhid/mouse/mousedev.c
r7a72ce1a ra1b7e80 183 183 /*----------------------------------------------------------------------------*/ 184 184 185 static void usb_mouse_ free(usb_mouse_t **mouse_dev)186 { 187 assert(mouse_dev != NULL && *mouse_dev != NULL);185 static void usb_mouse_destroy(usb_mouse_t *mouse_dev) 186 { 187 assert(mouse_dev != NULL); 188 188 189 189 // hangup phone to the console 190 if ((*mouse_dev)->mouse_phone >= 0) { 191 async_obsolete_hangup((*mouse_dev)->mouse_phone); 192 } 193 194 if ((*mouse_dev)->wheel_phone >= 0) { 195 async_obsolete_hangup((*mouse_dev)->wheel_phone); 196 } 197 198 free(*mouse_dev); 199 *mouse_dev = NULL; 190 if (mouse_dev->mouse_phone >= 0) { 191 async_obsolete_hangup(mouse_dev->mouse_phone); 192 } 193 194 if (mouse_dev->wheel_phone >= 0) { 195 async_obsolete_hangup(mouse_dev->wheel_phone); 196 } 200 197 } 201 198 … … 437 434 int rc = usb_mouse_create_function(hid_dev, mouse_dev); 438 435 if (rc != EOK) { 439 usb_mouse_ free(&mouse_dev);436 usb_mouse_destroy(mouse_dev); 440 437 return rc; 441 438 } … … 464 461 { 465 462 if (data != NULL) { 466 usb_mouse_ free((usb_mouse_t **)&data);463 usb_mouse_destroy((usb_mouse_t *)data); 467 464 } 468 465 } -
uspace/drv/bus/usb/usbhid/multimedia/multimedia.c
r7a72ce1a ra1b7e80 167 167 /*----------------------------------------------------------------------------*/ 168 168 169 static void usb_multimedia_free(usb_multimedia_t **multim_dev)170 {171 if (multim_dev == NULL || *multim_dev == NULL) {172 return;173 }174 175 // hangup phone to the console176 async_obsolete_hangup((*multim_dev)->console_phone);177 178 free(*multim_dev);179 *multim_dev = NULL;180 }181 182 /*----------------------------------------------------------------------------*/183 184 169 static int usb_multimedia_create_function(usb_hid_dev_t *hid_dev, 185 170 usb_multimedia_t *multim_dev) … … 247 232 248 233 int rc = usb_multimedia_create_function(hid_dev, multim_dev); 249 if (rc != EOK) { 250 usb_multimedia_free(&multim_dev); 234 if (rc != EOK) 251 235 return rc; 252 }253 236 254 237 usb_log_debug(NAME " HID/multimedia structure initialized.\n"); … … 267 250 if (data != NULL) { 268 251 usb_multimedia_t *multim_dev = (usb_multimedia_t *)data; 269 usb_multimedia_free(&multim_dev); 252 // hangup phone to the console 253 async_obsolete_hangup(multim_dev->console_phone); 270 254 } 271 255 } -
uspace/drv/bus/usb/usbhid/usbhid.c
r7a72ce1a ra1b7e80 627 627 } 628 628 629 usb_hid_ free(&hid_dev);629 usb_hid_destroy(hid_dev); 630 630 } 631 631 … … 646 646 /*----------------------------------------------------------------------------*/ 647 647 648 void usb_hid_ free(usb_hid_dev_t **hid_dev)648 void usb_hid_destroy(usb_hid_dev_t *hid_dev) 649 649 { 650 650 int i; 651 651 652 if (hid_dev == NULL || *hid_dev == NULL) {652 if (hid_dev == NULL) { 653 653 return; 654 654 } 655 655 656 656 usb_log_debug("Subdrivers: %p, subdriver count: %d\n", 657 (*hid_dev)->subdrivers, (*hid_dev)->subdriver_count);658 659 assert( (*hid_dev)->subdrivers != NULL660 || (*hid_dev)->subdriver_count == 0);661 662 for (i = 0; i < (*hid_dev)->subdriver_count; ++i) {663 if ( (*hid_dev)->subdrivers[i].deinit != NULL) {664 (*hid_dev)->subdrivers[i].deinit(*hid_dev,665 (*hid_dev)->subdrivers[i].data);657 hid_dev->subdrivers, hid_dev->subdriver_count); 658 659 assert(hid_dev->subdrivers != NULL 660 || hid_dev->subdriver_count == 0); 661 662 for (i = 0; i < hid_dev->subdriver_count; ++i) { 663 if (hid_dev->subdrivers[i].deinit != NULL) { 664 hid_dev->subdrivers[i].deinit(hid_dev, 665 hid_dev->subdrivers[i].data); 666 666 } 667 667 } 668 668 669 669 // free the subdrivers info 670 if ( (*hid_dev)->subdrivers != NULL) {671 free( (*hid_dev)->subdrivers);670 if (hid_dev->subdrivers != NULL) { 671 free(hid_dev->subdrivers); 672 672 } 673 673 674 674 // destroy the parser 675 if ((*hid_dev)->report != NULL) { 676 usb_hid_free_report((*hid_dev)->report); 677 } 678 679 if ((*hid_dev)->report_desc != NULL) { 680 free((*hid_dev)->report_desc); 681 } 682 683 free(*hid_dev); 684 *hid_dev = NULL; 675 if (hid_dev->report != NULL) { 676 usb_hid_free_report(hid_dev->report); 677 } 678 679 if (hid_dev->report_desc != NULL) { 680 free(hid_dev->report_desc); 681 } 685 682 } 686 683 -
uspace/drv/bus/usb/usbhid/usbhid.h
r7a72ce1a ra1b7e80 158 158 int usb_hid_report_number(usb_hid_dev_t *hid_dev); 159 159 160 void usb_hid_ free(usb_hid_dev_t **hid_dev);160 void usb_hid_destroy(usb_hid_dev_t *hid_dev); 161 161 162 162 #endif /* USB_HID_USBHID_H_ */ -
uspace/drv/bus/usb/usbmast/main.c
r7a72ce1a ra1b7e80 145 145 usbmast_fun_t *mfun = NULL; 146 146 147 /* Allocate softstate */148 mfun = calloc(1, sizeof(usbmast_fun_t));149 if (mfun == NULL) {150 usb_log_error("Failed allocating softstate.\n");151 rc = ENOMEM;152 goto error;153 }154 155 mfun->mdev = mdev;156 mfun->lun = lun;157 158 147 if (asprintf(&fun_name, "l%u", lun) < 0) { 159 148 usb_log_error("Out of memory.\n"); … … 170 159 171 160 free(fun_name); 161 162 /* Allocate soft state */ 163 mfun = ddf_dev_data_alloc(mdev->ddf_dev, sizeof(usbmast_fun_t)); 164 if (mfun == NULL) { 165 usb_log_error("Failed allocating softstate.\n"); 166 rc = ENOMEM; 167 goto error; 168 } 169 170 mfun->mdev = mdev; 171 mfun->lun = lun; 172 172 173 fun_name = NULL; 173 174 … … 227 228 if (fun_name != NULL) 228 229 free(fun_name); 229 if (mfun != NULL)230 free(mfun);231 230 return rc; 232 231 } -
uspace/drv/char/ns8250/ns8250.c
r7a72ce1a ra1b7e80 112 112 fibril_mutex_t mutex; 113 113 } ns8250_t; 114 115 /** Create per-device soft-state structure.116 *117 * @return Pointer to soft-state structure.118 */119 static ns8250_t *ns8250_new(void)120 {121 ns8250_t *ns;122 123 ns = (ns8250_t *) calloc(1, sizeof(ns8250_t));124 if (ns == NULL)125 return NULL;126 127 fibril_mutex_initialize(&ns->mutex);128 return ns;129 }130 131 /** Delete soft-state structure.132 *133 * @param ns The driver data structure.134 */135 static void ns8250_delete(ns8250_t *ns)136 {137 assert(ns != NULL);138 free(ns);139 }140 114 141 115 /** Find out if there is some incomming data available on the serial port. … … 721 695 722 696 /* Allocate soft-state for the device */ 723 ns = ns8250_new();697 ns = ddf_dev_data_alloc(dev, sizeof(ns8250_t)); 724 698 if (ns == NULL) { 725 699 rc = ENOMEM; … … 727 701 } 728 702 703 fibril_mutex_initialize(&ns->mutex); 729 704 ns->dev = dev; 730 dev->driver_data = ns;731 705 732 706 rc = ns8250_dev_initialize(ns); … … 792 766 if (need_cleanup) 793 767 ns8250_dev_cleanup(ns); 794 if (ns != NULL)795 ns8250_delete(ns);796 768 return rc; 797 769 } -
uspace/drv/infrastructure/rootvirt/rootvirt.c
r7a72ce1a ra1b7e80 63 63 64 64 static int rootvirt_add_device(ddf_dev_t *dev); 65 static int rootvirt_fun_online(ddf_fun_t *fun); 66 static int rootvirt_fun_offline(ddf_fun_t *fun); 65 67 66 68 static driver_ops_t rootvirt_ops = { 67 .add_device = &rootvirt_add_device 69 .add_device = &rootvirt_add_device, 70 .fun_online = &rootvirt_fun_online, 71 .fun_offline = &rootvirt_fun_offline 68 72 }; 69 73 … … 140 144 } 141 145 146 static int rootvirt_fun_online(ddf_fun_t *fun) 147 { 148 ddf_msg(LVL_DEBUG, "rootvirt_fun_online()"); 149 return ddf_fun_online(fun); 150 } 151 152 static int rootvirt_fun_offline(ddf_fun_t *fun) 153 { 154 ddf_msg(LVL_DEBUG, "rootvirt_fun_offline()"); 155 return ddf_fun_offline(fun); 156 } 157 142 158 int main(int argc, char *argv[]) 143 159 { -
uspace/drv/test/test1/test1.c
r7a72ce1a ra1b7e80 1 1 /* 2 2 * Copyright (c) 2010 Vojtech Horky 3 * Copyright (c) 2011 Jiri Svoboda 3 4 * All rights reserved. 4 5 * … … 40 41 41 42 static int test1_add_device(ddf_dev_t *dev); 43 static int test1_dev_remove(ddf_dev_t *dev); 44 static int test1_fun_online(ddf_fun_t *fun); 45 static int test1_fun_offline(ddf_fun_t *fun); 42 46 43 47 static driver_ops_t driver_ops = { 44 .add_device = &test1_add_device 48 .add_device = &test1_add_device, 49 .dev_remove = &test1_dev_remove, 50 .fun_online = &test1_fun_online, 51 .fun_offline = &test1_fun_offline 45 52 }; 46 53 … … 49 56 .driver_ops = &driver_ops 50 57 }; 58 59 typedef struct { 60 ddf_fun_t *fun_a; 61 ddf_fun_t *clone; 62 ddf_fun_t *child; 63 } test1_t; 51 64 52 65 /** Register child and inform user about it. … … 60 73 static int register_fun_verbose(ddf_dev_t *parent, const char *message, 61 74 const char *name, const char *match_id, int match_score, 62 int expected_rc )75 int expected_rc, ddf_fun_t **pfun) 63 76 { 64 77 ddf_fun_t *fun = NULL; … … 103 116 } 104 117 118 if (pfun != NULL) 119 *pfun = fun; 120 105 121 return rc; 106 122 } … … 126 142 { 127 143 ddf_fun_t *fun_a; 144 test1_t *test1; 128 145 int rc; 129 146 130 147 ddf_msg(LVL_DEBUG, "add_device(name=\"%s\", handle=%d)", 131 148 dev->name, (int) dev->handle); 149 150 test1 = ddf_dev_data_alloc(dev, sizeof(test1_t)); 151 if (test1 == NULL) { 152 ddf_msg(LVL_ERROR, "Failed allocating soft state.\n"); 153 return ENOMEM; 154 } 132 155 133 156 fun_a = ddf_fun_create(dev, fun_exposed, "a"); … … 137 160 } 138 161 162 test1->fun_a = fun_a; 163 139 164 rc = ddf_fun_bind(fun_a); 140 165 if (rc != EOK) { 141 166 ddf_msg(LVL_ERROR, "Failed binding function 'a'."); 167 ddf_fun_destroy(fun_a); 142 168 return rc; 143 169 } … … 151 177 (void) register_fun_verbose(dev, 152 178 "cloning myself ;-)", "clone", 153 "virtual&test1", 10, EOK );179 "virtual&test1", 10, EOK, &test1->clone); 154 180 (void) register_fun_verbose(dev, 155 181 "cloning myself twice ;-)", "clone", 156 "virtual&test1", 10, EEXISTS );182 "virtual&test1", 10, EEXISTS, NULL); 157 183 } else if (str_cmp(dev->name, "clone") == 0) { 158 184 (void) register_fun_verbose(dev, 159 185 "run by the same task", "child", 160 "virtual&test1&child", 10, EOK );186 "virtual&test1&child", 10, EOK, &test1->child); 161 187 } 162 188 … … 164 190 165 191 return EOK; 192 } 193 194 static int fun_remove(ddf_fun_t *fun, const char *name) 195 { 196 int rc; 197 198 ddf_msg(LVL_DEBUG, "fun_remove(%p, '%s')\n", fun, name); 199 rc = ddf_fun_offline(fun); 200 if (rc != EOK) { 201 ddf_msg(LVL_ERROR, "Error offlining function '%s'.", name); 202 return rc; 203 } 204 205 rc = ddf_fun_unbind(fun); 206 if (rc != EOK) { 207 ddf_msg(LVL_ERROR, "Failed offlining function '%s'.", name); 208 return rc; 209 } 210 211 ddf_fun_destroy(fun); 212 return EOK; 213 } 214 215 static int test1_dev_remove(ddf_dev_t *dev) 216 { 217 test1_t *test1 = (test1_t *)dev->driver_data; 218 int rc; 219 220 ddf_msg(LVL_DEBUG, "test1_dev_remove(%p)", dev); 221 222 if (test1->fun_a != NULL) { 223 rc = fun_remove(test1->fun_a, "a"); 224 if (rc != EOK) 225 return rc; 226 } 227 228 if (test1->clone != NULL) { 229 rc = fun_remove(test1->clone, "clone"); 230 if (rc != EOK) 231 return rc; 232 } 233 234 if (test1->child != NULL) { 235 rc = fun_remove(test1->child, "child"); 236 if (rc != EOK) 237 return rc; 238 } 239 240 return EOK; 241 } 242 243 static int test1_fun_online(ddf_fun_t *fun) 244 { 245 ddf_msg(LVL_DEBUG, "test1_fun_online()"); 246 return ddf_fun_online(fun); 247 } 248 249 static int test1_fun_offline(ddf_fun_t *fun) 250 { 251 ddf_msg(LVL_DEBUG, "test1_fun_offline()"); 252 return ddf_fun_offline(fun); 166 253 } 167 254 -
uspace/lib/c/generic/devman.c
r7a72ce1a ra1b7e80 327 327 } 328 328 329 int devman_drv_fun_online(devman_handle_t funh) 330 { 331 async_exch_t *exch = devman_exchange_begin(DEVMAN_DRIVER); 332 if (exch == NULL) 333 return ENOMEM; 334 335 sysarg_t retval = async_req_1_0(exch, DEVMAN_DRV_FUN_ONLINE, funh); 336 337 devman_exchange_end(exch); 338 return (int) retval; 339 } 340 341 int devman_drv_fun_offline(devman_handle_t funh) 342 { 343 async_exch_t *exch = devman_exchange_begin(DEVMAN_DRIVER); 344 if (exch == NULL) 345 return ENOMEM; 346 347 sysarg_t retval = async_req_1_0(exch, DEVMAN_DRV_FUN_OFFLINE, funh); 348 349 devman_exchange_end(exch); 350 return (int) retval; 351 } 352 329 353 async_sess_t *devman_parent_device_connect(exch_mgmt_t mgmt, 330 354 devman_handle_t handle, unsigned int flags) … … 430 454 } 431 455 456 int devman_fun_online(devman_handle_t funh) 457 { 458 async_exch_t *exch = devman_exchange_begin(DEVMAN_CLIENT); 459 if (exch == NULL) 460 return ENOMEM; 461 462 sysarg_t retval = async_req_1_0(exch, DEVMAN_FUN_ONLINE, funh); 463 464 devman_exchange_end(exch); 465 return (int) retval; 466 } 467 468 int devman_fun_offline(devman_handle_t funh) 469 { 470 async_exch_t *exch = devman_exchange_begin(DEVMAN_CLIENT); 471 if (exch == NULL) 472 return ENOMEM; 473 474 sysarg_t retval = async_req_1_0(exch, DEVMAN_FUN_OFFLINE, funh); 475 476 devman_exchange_end(exch); 477 return (int) retval; 478 } 479 432 480 static int devman_get_handles_once(sysarg_t method, sysarg_t arg1, 433 481 devman_handle_t *handle_buf, size_t buf_size, size_t *act_size) -
uspace/lib/c/include/devman.h
r7a72ce1a ra1b7e80 50 50 devman_handle_t, devman_handle_t *); 51 51 extern int devman_remove_function(devman_handle_t); 52 extern int devman_drv_fun_online(devman_handle_t); 53 extern int devman_drv_fun_offline(devman_handle_t); 52 54 53 55 extern async_sess_t *devman_device_connect(exch_mgmt_t, devman_handle_t, … … 63 65 extern int devman_fun_get_name(devman_handle_t, char *, size_t); 64 66 extern int devman_fun_get_path(devman_handle_t, char *, size_t); 67 extern int devman_fun_online(devman_handle_t); 68 extern int devman_fun_offline(devman_handle_t); 65 69 66 70 extern int devman_add_device_to_category(devman_handle_t, const char *); -
uspace/lib/c/include/ipc/devman.h
r7a72ce1a ra1b7e80 139 139 DEVMAN_ADD_MATCH_ID, 140 140 DEVMAN_ADD_DEVICE_TO_CATEGORY, 141 DEVMAN_DRV_FUN_ONLINE, 142 DEVMAN_DRV_FUN_OFFLINE, 141 143 DEVMAN_REMOVE_FUNCTION 142 144 } driver_to_devman_t; 143 145 144 146 typedef enum { 145 DRIVER_ADD_DEVICE = IPC_FIRST_USER_METHOD 147 DRIVER_DEV_ADD = IPC_FIRST_USER_METHOD, 148 DRIVER_DEV_REMOVE, 149 DRIVER_FUN_ONLINE, 150 DRIVER_FUN_OFFLINE, 146 151 147 152 } devman_to_driver_t; … … 152 157 DEVMAN_FUN_GET_CHILD, 153 158 DEVMAN_FUN_GET_NAME, 159 DEVMAN_FUN_ONLINE, 160 DEVMAN_FUN_OFFLINE, 154 161 DEVMAN_FUN_GET_PATH, 155 162 DEVMAN_FUN_SID_TO_HANDLE -
uspace/lib/drv/generic/driver.c
r7a72ce1a ra1b7e80 63 63 64 64 /** Devices */ 65 LIST_INITIALIZE(devices); 66 FIBRIL_MUTEX_INITIALIZE(devices_mutex); 67 68 /** Functions */ 65 69 LIST_INITIALIZE(functions); 66 70 FIBRIL_MUTEX_INITIALIZE(functions_mutex); … … 82 86 static ddf_dev_t *create_device(void); 83 87 static void delete_device(ddf_dev_t *); 88 static void dev_add_ref(ddf_dev_t *); 89 static void dev_del_ref(ddf_dev_t *); 90 static void fun_add_ref(ddf_fun_t *); 91 static void fun_del_ref(ddf_fun_t *); 84 92 static remote_handler_t *function_get_default_handler(ddf_fun_t *); 85 93 static void *function_get_ops(ddf_fun_t *, dev_inferface_idx_t); … … 227 235 } 228 236 229 static ddf_fun_t *driver_get_function(list_t *functions, devman_handle_t handle) 237 static ddf_dev_t *driver_get_device(devman_handle_t handle) 238 { 239 ddf_dev_t *dev = NULL; 240 241 assert(fibril_mutex_is_locked(&devices_mutex)); 242 243 list_foreach(devices, link) { 244 dev = list_get_instance(link, ddf_dev_t, link); 245 if (dev->handle == handle) 246 return dev; 247 } 248 249 return NULL; 250 } 251 252 static ddf_fun_t *driver_get_function(devman_handle_t handle) 230 253 { 231 254 ddf_fun_t *fun = NULL; 232 255 233 fibril_mutex_lock(&functions_mutex);234 235 list_foreach( *functions, link) {256 assert(fibril_mutex_is_locked(&functions_mutex)); 257 258 list_foreach(functions, link) { 236 259 fun = list_get_instance(link, ddf_fun_t, link); 237 if (fun->handle == handle) { 238 fibril_mutex_unlock(&functions_mutex); 260 if (fun->handle == handle) 239 261 return fun; 240 } 241 } 242 243 fibril_mutex_unlock(&functions_mutex); 262 } 244 263 245 264 return NULL; 246 265 } 247 266 248 static void driver_ add_device(ipc_callid_t iid, ipc_call_t *icall)267 static void driver_dev_add(ipc_callid_t iid, ipc_call_t *icall) 249 268 { 250 269 char *dev_name = NULL; … … 255 274 256 275 ddf_dev_t *dev = create_device(); 276 277 /* Add one reference that will be dropped by driver_dev_remove() */ 278 dev_add_ref(dev); 257 279 dev->handle = dev_handle; 258 280 … … 267 289 268 290 res = driver->driver_ops->add_device(dev); 269 if (res != EOK) 270 delete_device(dev); 291 292 if (res != EOK) { 293 dev_del_ref(dev); 294 async_answer_0(iid, res); 295 return; 296 } 297 298 fibril_mutex_lock(&devices_mutex); 299 list_append(&dev->link, &devices); 300 fibril_mutex_unlock(&devices_mutex); 271 301 272 302 async_answer_0(iid, res); 303 } 304 305 static void driver_dev_remove(ipc_callid_t iid, ipc_call_t *icall) 306 { 307 devman_handle_t devh; 308 ddf_dev_t *dev; 309 int rc; 310 311 devh = IPC_GET_ARG1(*icall); 312 313 fibril_mutex_lock(&devices_mutex); 314 dev = driver_get_device(devh); 315 dev_add_ref(dev); 316 fibril_mutex_unlock(&devices_mutex); 317 318 if (dev == NULL) { 319 async_answer_0(iid, ENOENT); 320 return; 321 } 322 323 if (driver->driver_ops->dev_remove != NULL) 324 rc = driver->driver_ops->dev_remove(dev); 325 else 326 rc = ENOTSUP; 327 328 if (rc == EOK) 329 dev_del_ref(dev); 330 331 async_answer_0(iid, (sysarg_t) rc); 332 } 333 334 static void driver_fun_online(ipc_callid_t iid, ipc_call_t *icall) 335 { 336 devman_handle_t funh; 337 ddf_fun_t *fun; 338 int rc; 339 340 funh = IPC_GET_ARG1(*icall); 341 342 /* 343 * Look the function up. Bump reference count so that 344 * the function continues to exist until we return 345 * from the driver. 346 */ 347 fibril_mutex_lock(&functions_mutex); 348 349 fun = driver_get_function(funh); 350 if (fun != NULL) 351 fun_add_ref(fun); 352 353 fibril_mutex_unlock(&functions_mutex); 354 355 if (fun == NULL) { 356 async_answer_0(iid, ENOENT); 357 return; 358 } 359 360 /* Call driver entry point */ 361 if (driver->driver_ops->fun_online != NULL) 362 rc = driver->driver_ops->fun_online(fun); 363 else 364 rc = ENOTSUP; 365 366 fun_del_ref(fun); 367 368 async_answer_0(iid, (sysarg_t) rc); 369 } 370 371 static void driver_fun_offline(ipc_callid_t iid, ipc_call_t *icall) 372 { 373 devman_handle_t funh; 374 ddf_fun_t *fun; 375 int rc; 376 377 funh = IPC_GET_ARG1(*icall); 378 379 /* 380 * Look the function up. Bump reference count so that 381 * the function continues to exist until we return 382 * from the driver. 383 */ 384 fibril_mutex_lock(&functions_mutex); 385 386 fun = driver_get_function(funh); 387 if (fun != NULL) 388 fun_add_ref(fun); 389 390 fibril_mutex_unlock(&functions_mutex); 391 392 if (fun == NULL) { 393 async_answer_0(iid, ENOENT); 394 return; 395 } 396 397 /* Call driver entry point */ 398 if (driver->driver_ops->fun_offline != NULL) 399 rc = driver->driver_ops->fun_offline(fun); 400 else 401 rc = ENOTSUP; 402 403 async_answer_0(iid, (sysarg_t) rc); 273 404 } 274 405 … … 286 417 287 418 switch (IPC_GET_IMETHOD(call)) { 288 case DRIVER_ADD_DEVICE: 289 driver_add_device(callid, &call); 419 case DRIVER_DEV_ADD: 420 driver_dev_add(callid, &call); 421 break; 422 case DRIVER_DEV_REMOVE: 423 driver_dev_remove(callid, &call); 424 break; 425 case DRIVER_FUN_ONLINE: 426 driver_fun_online(callid, &call); 427 break; 428 case DRIVER_FUN_OFFLINE: 429 driver_fun_offline(callid, &call); 290 430 break; 291 431 default: 292 async_answer_0(callid, ENO ENT);432 async_answer_0(callid, ENOTSUP); 293 433 } 294 434 } … … 308 448 */ 309 449 devman_handle_t handle = IPC_GET_ARG2(*icall); 310 ddf_fun_t *fun = driver_get_function(&functions, handle); 450 451 fibril_mutex_lock(&functions_mutex); 452 ddf_fun_t *fun = driver_get_function(handle); 453 fibril_mutex_unlock(&functions_mutex); 454 /* XXX Need a lock on fun */ 311 455 312 456 if (fun == NULL) { … … 466 610 ddf_dev_t *dev; 467 611 468 dev = malloc(sizeof(ddf_dev_t));612 dev = calloc(1, sizeof(ddf_dev_t)); 469 613 if (dev == NULL) 470 614 return NULL; 471 615 472 memset(dev, 0, sizeof(ddf_dev_t));473 616 return dev; 474 617 } … … 498 641 static void delete_device(ddf_dev_t *dev) 499 642 { 643 if (dev->driver_data != NULL) 644 free(dev->driver_data); 500 645 free(dev); 501 646 } 502 647 503 /** Delete devicestructure.648 /** Delete function structure. 504 649 * 505 650 * @param dev The device structure. … … 508 653 { 509 654 clean_match_ids(&fun->match_ids); 655 if (fun->driver_data != NULL) 656 free(fun->driver_data); 510 657 if (fun->name != NULL) 511 658 free(fun->name); … … 513 660 } 514 661 662 /** Increase device reference count. */ 663 static void dev_add_ref(ddf_dev_t *dev) 664 { 665 atomic_inc(&dev->refcnt); 666 } 667 668 /** Decrease device reference count. 669 * 670 * Free the device structure if the reference count drops to zero. 671 */ 672 static void dev_del_ref(ddf_dev_t *dev) 673 { 674 if (atomic_predec(&dev->refcnt) == 0) 675 delete_device(dev); 676 } 677 678 /** Increase function reference count. 679 * 680 * This also increases reference count on the device. The device structure 681 * will thus not be deallocated while there are some associated function 682 * structures. 683 */ 684 static void fun_add_ref(ddf_fun_t *fun) 685 { 686 dev_add_ref(fun->dev); 687 atomic_inc(&fun->refcnt); 688 } 689 690 /** Decrease function reference count. 691 * 692 * Free the function structure if the reference count drops to zero. 693 */ 694 static void fun_del_ref(ddf_fun_t *fun) 695 { 696 ddf_dev_t *dev = fun->dev; 697 698 if (atomic_predec(&fun->refcnt) == 0) 699 delete_function(fun); 700 701 dev_del_ref(dev); 702 } 703 704 /** Allocate driver-specific device data. */ 705 extern void *ddf_dev_data_alloc(ddf_dev_t *dev, size_t size) 706 { 707 void *data; 708 709 assert(dev->driver_data == NULL); 710 711 data = calloc(1, size); 712 if (data == NULL) 713 return NULL; 714 715 dev->driver_data = data; 716 return data; 717 } 718 515 719 /** Create a DDF function node. 516 720 * … … 544 748 return NULL; 545 749 750 /* Add one reference that will be dropped by ddf_fun_destroy() */ 751 fun->dev = dev; 752 fun_add_ref(fun); 753 546 754 fun->bound = false; 547 fun->dev = dev;548 755 fun->ftype = ftype; 549 756 … … 557 764 } 558 765 766 /** Allocate driver-specific function data. */ 767 extern void *ddf_fun_data_alloc(ddf_fun_t *fun, size_t size) 768 { 769 void *data; 770 771 assert(fun->bound == false); 772 assert(fun->driver_data == NULL); 773 774 data = calloc(1, size); 775 if (data == NULL) 776 return NULL; 777 778 fun->driver_data = data; 779 return data; 780 } 781 559 782 /** Destroy DDF function node. 560 783 * … … 567 790 { 568 791 assert(fun->bound == false); 569 delete_function(fun); 792 793 /* 794 * Drop the reference added by ddf_fun_create(). This will deallocate 795 * the function as soon as all other references are dropped (i.e. 796 * as soon control leaves all driver entry points called in context 797 * of this function. 798 */ 799 fun_del_ref(fun); 570 800 } 571 801 … … 614 844 * the function invisible to the system. 615 845 * 616 * @param fun Function to bind846 * @param fun Function to unbind 617 847 * @return EOK on success or negative error code 618 848 */ … … 623 853 assert(fun->bound == true); 624 854 625 add_to_functions_list(fun);626 855 res = devman_remove_function(fun->handle); 627 856 if (res != EOK) … … 631 860 632 861 fun->bound = false; 862 return EOK; 863 } 864 865 /** Online function. 866 * 867 * @param fun Function to online 868 * @return EOK on success or negative error code 869 */ 870 int ddf_fun_online(ddf_fun_t *fun) 871 { 872 int res; 873 874 assert(fun->bound == true); 875 876 res = devman_drv_fun_online(fun->handle); 877 if (res != EOK) 878 return res; 879 880 return EOK; 881 } 882 883 /** Offline function. 884 * 885 * @param fun Function to offline 886 * @return EOK on success or negative error code 887 */ 888 int ddf_fun_offline(ddf_fun_t *fun) 889 { 890 int res; 891 892 assert(fun->bound == true); 893 894 res = devman_drv_fun_offline(fun->handle); 895 if (res != EOK) 896 return res; 897 633 898 return EOK; 634 899 } -
uspace/lib/drv/include/ddf/driver.h
r7a72ce1a ra1b7e80 81 81 */ 82 82 devman_handle_t handle; 83 /** Reference count */ 84 atomic_t refcnt; 83 85 84 86 /** … … 104 106 /** Function indentifier (asigned by device manager) */ 105 107 devman_handle_t handle; 108 /** Reference count */ 109 atomic_t refcnt; 106 110 107 111 /** Device which this function belogs to */ … … 132 136 typedef struct driver_ops { 133 137 /** Callback method for passing a new device to the device driver */ 134 int (*add_device)(ddf_dev_t *dev); 135 /* TODO: add other generic driver operations */ 138 int (*add_device)(ddf_dev_t *); 139 /** Ask driver to remove a device */ 140 int (*dev_remove)(ddf_dev_t *); 141 /** Ask driver to online a specific function */ 142 int (*fun_online)(ddf_fun_t *); 143 /** Ask driver to offline a specific function */ 144 int (*fun_offline)(ddf_fun_t *); 136 145 } driver_ops_t; 137 146 … … 146 155 extern int ddf_driver_main(driver_t *); 147 156 157 extern void *ddf_dev_data_alloc(ddf_dev_t *, size_t); 148 158 extern ddf_fun_t *ddf_fun_create(ddf_dev_t *, fun_type_t, const char *); 149 159 extern void ddf_fun_destroy(ddf_fun_t *); 160 extern void *ddf_fun_data_alloc(ddf_fun_t *, size_t); 150 161 extern int ddf_fun_bind(ddf_fun_t *); 151 162 extern int ddf_fun_unbind(ddf_fun_t *); 163 extern int ddf_fun_online(ddf_fun_t *); 164 extern int ddf_fun_offline(ddf_fun_t *); 152 165 extern int ddf_fun_add_match_id(ddf_fun_t *, const char *, int); 153 166 -
uspace/srv/devman/devman.c
r7a72ce1a ra1b7e80 30 30 * @{ 31 31 */ 32 /** @file Device Manager 33 * 34 * Locking order: 35 * (1) driver_t.driver_mutex 36 * (2) dev_tree_t.rwlock 37 * 38 * Synchronization: 39 * - device_tree.rwlock protects: 40 * - tree root, complete tree topology 41 * - complete contents of device and function nodes 42 * - dev_node_t.refcnt, fun_node_t.refcnt prevent nodes from 43 * being deallocated 44 * - find_xxx() functions increase reference count of returned object 45 * - find_xxx_no_lock() do not increase reference count 46 * 47 * TODO 48 * - Track all steady and transient device/function states 49 * - Check states, wait for steady state on certain operations 50 */ 32 51 33 52 #include <errno.h> … … 43 62 #include "devman.h" 44 63 45 fun_node_t *find_node_child(fun_node_t *parent, const char *name);64 static fun_node_t *find_node_child(dev_tree_t *, fun_node_t *, const char *); 46 65 47 66 /* hash table operations */ … … 406 425 } 407 426 427 fun_add_ref(fun); 408 428 insert_fun_node(tree, fun, str_dup(""), NULL); 429 409 430 match_id_t *id = create_match_id(); 410 431 id->id = str_dup("root"); … … 422 443 } 423 444 445 dev_add_ref(dev); 424 446 insert_dev_node(tree, dev, fun); 425 447 … … 467 489 /** Assign a driver to a device. 468 490 * 491 * @param tree Device tree 469 492 * @param node The device's node in the device tree. 470 493 * @param drv The driver. 471 494 */ 472 void attach_driver(dev_ node_t *dev, driver_t *drv)495 void attach_driver(dev_tree_t *tree, dev_node_t *dev, driver_t *drv) 473 496 { 474 497 log_msg(LVL_DEBUG, "attach_driver(dev=\"%s\",drv=\"%s\")", … … 476 499 477 500 fibril_mutex_lock(&drv->driver_mutex); 501 fibril_rwlock_write_lock(&tree->rwlock); 478 502 479 503 dev->drv = drv; 480 504 list_append(&dev->driver_devices, &drv->devices); 481 505 506 fibril_rwlock_write_unlock(&tree->rwlock); 507 fibril_mutex_unlock(&drv->driver_mutex); 508 } 509 510 /** Detach driver from device. 511 * 512 * @param tree Device tree 513 * @param node The device's node in the device tree. 514 * @param drv The driver. 515 */ 516 void detach_driver(dev_tree_t *tree, dev_node_t *dev) 517 { 518 driver_t *drv = dev->drv; 519 520 assert(drv != NULL); 521 522 log_msg(LVL_DEBUG, "detach_driver(dev=\"%s\",drv=\"%s\")", 523 dev->pfun->pathname, drv->name); 524 525 fibril_mutex_lock(&drv->driver_mutex); 526 fibril_rwlock_write_lock(&tree->rwlock); 527 528 dev->drv = NULL; 529 list_remove(&dev->driver_devices); 530 531 fibril_rwlock_write_unlock(&tree->rwlock); 482 532 fibril_mutex_unlock(&drv->driver_mutex); 483 533 } … … 556 606 while (link != &driver->devices.head) { 557 607 dev = list_get_instance(link, dev_node_t, driver_devices); 608 fibril_rwlock_write_lock(&tree->rwlock); 609 558 610 if (dev->passed_to_driver) { 611 fibril_rwlock_write_unlock(&tree->rwlock); 559 612 link = link->next; 560 613 continue; 561 614 } 562 615 563 /* 564 * We remove the device from the list to allow safe adding 565 * of new devices (no one will touch our item this way). 566 */ 567 list_remove(link); 616 log_msg(LVL_DEBUG, "pass_devices_to_driver: dev->refcnt=%d\n", 617 (int)atomic_get(&dev->refcnt)); 618 dev_add_ref(dev); 568 619 569 620 /* … … 572 623 */ 573 624 fibril_mutex_unlock(&driver->driver_mutex); 625 fibril_rwlock_write_unlock(&tree->rwlock); 574 626 575 627 add_device(driver, dev, tree); 628 629 dev_del_ref(dev); 576 630 577 631 /* … … 580 634 */ 581 635 fibril_mutex_lock(&driver->driver_mutex); 582 583 /*584 * Insert the device back.585 * The order is not relevant here so no harm is done586 * (actually, the order would be preserved in most cases).587 */588 list_append(link, &driver->devices);589 636 590 637 /* … … 679 726 char *loc_name = NULL; 680 727 728 assert(fibril_rwlock_is_locked(&tree->rwlock)); 729 681 730 asprintf(&loc_name, "%s", fun->pathname); 682 731 if (loc_name == NULL) … … 726 775 727 776 ipc_call_t answer; 728 aid_t req = async_send_2(exch, DRIVER_ ADD_DEVICE, dev->handle,777 aid_t req = async_send_2(exch, DRIVER_DEV_ADD, dev->handle, 729 778 parent_handle, &answer); 730 779 … … 783 832 784 833 /* Attach the driver to the device. */ 785 attach_driver( dev, drv);834 attach_driver(tree, dev, drv); 786 835 787 836 fibril_mutex_lock(&drv->driver_mutex); … … 797 846 add_device(drv, dev, tree); 798 847 848 fibril_mutex_lock(&drv->driver_mutex); 849 fibril_mutex_unlock(&drv->driver_mutex); 850 851 fibril_rwlock_write_lock(&tree->rwlock); 852 if (dev->pfun != NULL) { 853 dev->pfun->state = FUN_ON_LINE; 854 } 855 fibril_rwlock_write_unlock(&tree->rwlock); 799 856 return true; 857 } 858 859 int driver_dev_remove(dev_tree_t *tree, dev_node_t *dev) 860 { 861 async_exch_t *exch; 862 sysarg_t retval; 863 driver_t *drv; 864 devman_handle_t handle; 865 866 assert(dev != NULL); 867 868 log_msg(LVL_DEBUG, "driver_dev_remove(%p)", dev); 869 870 fibril_rwlock_read_lock(&tree->rwlock); 871 drv = dev->drv; 872 handle = dev->handle; 873 fibril_rwlock_read_unlock(&tree->rwlock); 874 875 exch = async_exchange_begin(drv->sess); 876 retval = async_req_1_0(exch, DRIVER_DEV_REMOVE, handle); 877 async_exchange_end(exch); 878 879 return retval; 880 881 } 882 883 int driver_fun_online(dev_tree_t *tree, fun_node_t *fun) 884 { 885 async_exch_t *exch; 886 sysarg_t retval; 887 driver_t *drv; 888 devman_handle_t handle; 889 890 log_msg(LVL_DEBUG, "driver_fun_online(%p)", fun); 891 892 fibril_rwlock_read_lock(&tree->rwlock); 893 894 if (fun->dev == NULL) { 895 /* XXX root function? */ 896 fibril_rwlock_read_unlock(&tree->rwlock); 897 return EINVAL; 898 } 899 900 drv = fun->dev->drv; 901 handle = fun->handle; 902 fibril_rwlock_read_unlock(&tree->rwlock); 903 904 exch = async_exchange_begin(drv->sess); 905 retval = async_req_1_0(exch, DRIVER_FUN_ONLINE, handle); 906 loc_exchange_end(exch); 907 908 return retval; 909 } 910 911 int driver_fun_offline(dev_tree_t *tree, fun_node_t *fun) 912 { 913 async_exch_t *exch; 914 sysarg_t retval; 915 driver_t *drv; 916 devman_handle_t handle; 917 918 log_msg(LVL_DEBUG, "driver_fun_offline(%p)", fun); 919 920 fibril_rwlock_read_lock(&tree->rwlock); 921 if (fun->dev == NULL) { 922 /* XXX root function? */ 923 fibril_rwlock_read_unlock(&tree->rwlock); 924 return EINVAL; 925 } 926 927 drv = fun->dev->drv; 928 handle = fun->handle; 929 fibril_rwlock_read_unlock(&tree->rwlock); 930 931 exch = async_exchange_begin(drv->sess); 932 retval = async_req_1_0(exch, DRIVER_FUN_OFFLINE, handle); 933 loc_exchange_end(exch); 934 935 return retval; 936 800 937 } 801 938 … … 826 963 if (!create_root_nodes(tree)) 827 964 return false; 828 965 829 966 /* Find suitable driver and start it. */ 830 return assign_driver(tree->root_node->child, drivers_list, tree); 967 dev_node_t *rdev = tree->root_node->child; 968 dev_add_ref(rdev); 969 int rc = assign_driver(rdev, drivers_list, tree); 970 dev_del_ref(rdev); 971 972 return rc; 831 973 } 832 974 … … 839 981 dev_node_t *create_dev_node(void) 840 982 { 841 dev_node_t *res = malloc(sizeof(dev_node_t)); 842 843 if (res != NULL) { 844 memset(res, 0, sizeof(dev_node_t)); 845 list_initialize(&res->functions); 846 link_initialize(&res->driver_devices); 847 link_initialize(&res->devman_dev); 848 } 849 850 return res; 983 dev_node_t *dev; 984 985 dev = calloc(1, sizeof(dev_node_t)); 986 if (dev == NULL) 987 return NULL; 988 989 atomic_set(&dev->refcnt, 0); 990 list_initialize(&dev->functions); 991 link_initialize(&dev->driver_devices); 992 link_initialize(&dev->devman_dev); 993 994 return dev; 851 995 } 852 996 … … 864 1008 } 865 1009 1010 /** Increase device node reference count. 1011 * 1012 * @param dev Device node 1013 */ 1014 void dev_add_ref(dev_node_t *dev) 1015 { 1016 atomic_inc(&dev->refcnt); 1017 } 1018 1019 /** Decrease device node reference count. 1020 * 1021 * When the count drops to zero the device node is freed. 1022 * 1023 * @param dev Device node 1024 */ 1025 void dev_del_ref(dev_node_t *dev) 1026 { 1027 if (atomic_predec(&dev->refcnt) == 0) 1028 delete_dev_node(dev); 1029 } 1030 1031 866 1032 /** Find the device node structure of the device witch has the specified handle. 867 1033 * … … 893 1059 fibril_rwlock_read_lock(&tree->rwlock); 894 1060 dev = find_dev_node_no_lock(tree, handle); 1061 if (dev != NULL) 1062 dev_add_ref(dev); 1063 895 1064 fibril_rwlock_read_unlock(&tree->rwlock); 896 1065 … … 920 1089 list_get_instance(item, fun_node_t, dev_functions); 921 1090 922 if (pos < buf_cnt) 1091 if (pos < buf_cnt) { 923 1092 hdl_buf[pos] = fun->handle; 1093 } 1094 924 1095 pos++; 925 1096 } … … 937 1108 fun_node_t *create_fun_node(void) 938 1109 { 939 fun_node_t *res = malloc(sizeof(fun_node_t)); 940 941 if (res != NULL) { 942 memset(res, 0, sizeof(fun_node_t)); 943 link_initialize(&res->dev_functions); 944 list_initialize(&res->match_ids.ids); 945 link_initialize(&res->devman_fun); 946 link_initialize(&res->loc_fun); 947 } 948 949 return res; 1110 fun_node_t *fun; 1111 1112 fun = calloc(1, sizeof(fun_node_t)); 1113 if (fun == NULL) 1114 return NULL; 1115 1116 fun->state = FUN_INIT; 1117 atomic_set(&fun->refcnt, 0); 1118 link_initialize(&fun->dev_functions); 1119 list_initialize(&fun->match_ids.ids); 1120 link_initialize(&fun->devman_fun); 1121 link_initialize(&fun->loc_fun); 1122 1123 return fun; 950 1124 } 951 1125 … … 965 1139 } 966 1140 1141 /** Increase function node reference count. 1142 * 1143 * @param fun Function node 1144 */ 1145 void fun_add_ref(fun_node_t *fun) 1146 { 1147 atomic_inc(&fun->refcnt); 1148 } 1149 1150 /** Decrease function node reference count. 1151 * 1152 * When the count drops to zero the function node is freed. 1153 * 1154 * @param fun Function node 1155 */ 1156 void fun_del_ref(fun_node_t *fun) 1157 { 1158 if (atomic_predec(&fun->refcnt) == 0) 1159 delete_fun_node(fun); 1160 } 1161 967 1162 /** Find the function node with the specified handle. 968 1163 * … … 975 1170 unsigned long key = handle; 976 1171 link_t *link; 1172 fun_node_t *fun; 977 1173 978 1174 assert(fibril_rwlock_is_locked(&tree->rwlock)); … … 982 1178 return NULL; 983 1179 984 return hash_table_get_instance(link, fun_node_t, devman_fun); 1180 fun = hash_table_get_instance(link, fun_node_t, devman_fun); 1181 1182 return fun; 985 1183 } 986 1184 … … 996 1194 997 1195 fibril_rwlock_read_lock(&tree->rwlock); 1196 998 1197 fun = find_fun_node_no_lock(tree, handle); 1198 if (fun != NULL) 1199 fun_add_ref(fun); 1200 999 1201 fibril_rwlock_read_unlock(&tree->rwlock); 1000 1202 … … 1004 1206 /** Create and set device's full path in device tree. 1005 1207 * 1208 * @param tree Device tree 1006 1209 * @param node The device's device node. 1007 1210 * @param parent The parent device node. … … 1009 1212 * resources etc.). 1010 1213 */ 1011 static bool set_fun_path(fun_node_t *fun, fun_node_t *parent) 1012 { 1214 static bool set_fun_path(dev_tree_t *tree, fun_node_t *fun, fun_node_t *parent) 1215 { 1216 assert(fibril_rwlock_is_write_locked(&tree->rwlock)); 1013 1217 assert(fun->name != NULL); 1014 1218 … … 1037 1241 * 1038 1242 * @param tree The device tree. 1039 * @param node The newly added device node. 1040 * @param dev_name The name of the newly added device. 1041 * @param parent The parent device node. 1243 * @param dev The newly added device node. 1244 * @param pfun The parent function node. 1042 1245 * 1043 1246 * @return True on success, false otherwise (insufficient resources … … 1046 1249 bool insert_dev_node(dev_tree_t *tree, dev_node_t *dev, fun_node_t *pfun) 1047 1250 { 1048 assert(dev != NULL);1049 assert(tree != NULL);1050 1251 assert(fibril_rwlock_is_write_locked(&tree->rwlock)); 1051 1252 … … 1065 1266 } 1066 1267 1268 /** Remove device from device tree. 1269 * 1270 * @param tree Device tree 1271 * @param dev Device node 1272 */ 1273 void remove_dev_node(dev_tree_t *tree, dev_node_t *dev) 1274 { 1275 assert(fibril_rwlock_is_write_locked(&tree->rwlock)); 1276 1277 log_msg(LVL_DEBUG, "remove_dev_node(dev=%p)", dev); 1278 1279 /* Remove node from the handle-to-node map. */ 1280 unsigned long key = dev->handle; 1281 hash_table_remove(&tree->devman_devices, &key, 1); 1282 1283 /* Unlink from parent function. */ 1284 dev->pfun->child = NULL; 1285 dev->pfun = NULL; 1286 1287 dev->state = DEVICE_REMOVED; 1288 } 1289 1290 1067 1291 /** Insert new function into device tree. 1068 1292 * 1069 1293 * @param tree The device tree. 1070 * @param nodeThe newly added function node.1071 * @param dev_name The name of the newly added function.1072 * @param parentOwning device node.1294 * @param fun The newly added function node. 1295 * @param fun_name The name of the newly added function. 1296 * @param dev Owning device node. 1073 1297 * 1074 1298 * @return True on success, false otherwise (insufficient resources … … 1080 1304 fun_node_t *pfun; 1081 1305 1082 assert(fun != NULL);1083 assert(tree != NULL);1084 1306 assert(fun_name != NULL); 1085 1307 assert(fibril_rwlock_is_write_locked(&tree->rwlock)); … … 1092 1314 1093 1315 fun->name = fun_name; 1094 if (!set_fun_path( fun, pfun)) {1316 if (!set_fun_path(tree, fun, pfun)) { 1095 1317 return false; 1096 1318 } … … 1116 1338 void remove_fun_node(dev_tree_t *tree, fun_node_t *fun) 1117 1339 { 1118 assert(tree != NULL);1119 assert(fun != NULL);1120 1340 assert(fibril_rwlock_is_write_locked(&tree->rwlock)); 1121 1341 … … 1127 1347 if (fun->dev != NULL) 1128 1348 list_remove(&fun->dev_functions); 1349 1350 fun->dev = NULL; 1351 fun->state = FUN_REMOVED; 1129 1352 } 1130 1353 … … 1148 1371 1149 1372 fun_node_t *fun = tree->root_node; 1373 fun_add_ref(fun); 1150 1374 /* 1151 1375 * Relative path to the function from its parent (but with '/' at the … … 1165 1389 } 1166 1390 1167 fun = find_node_child(fun, rel_path + 1); 1391 fun_node_t *cfun = find_node_child(tree, fun, rel_path + 1); 1392 fun_del_ref(fun); 1393 fun = cfun; 1168 1394 1169 1395 if (cont) { … … 1183 1409 * Device tree rwlock should be held at least for reading. 1184 1410 * 1411 * @param tree Device tree 1185 1412 * @param dev Device the function belongs to. 1186 1413 * @param name Function name (not path). … … 1188 1415 * @retval NULL No function with given name. 1189 1416 */ 1190 fun_node_t *find_fun_node_in_device(dev_ node_t *dev, const char *name)1191 { 1192 assert(dev != NULL); 1417 fun_node_t *find_fun_node_in_device(dev_tree_t *tree, dev_node_t *dev, 1418 const char *name) 1419 { 1193 1420 assert(name != NULL); 1421 assert(fibril_rwlock_is_locked(&tree->rwlock)); 1194 1422 1195 1423 fun_node_t *fun; … … 1198 1426 fun = list_get_instance(link, fun_node_t, dev_functions); 1199 1427 1200 if (str_cmp(name, fun->name) == 0) 1428 if (str_cmp(name, fun->name) == 0) { 1429 fun_add_ref(fun); 1201 1430 return fun; 1431 } 1202 1432 } 1203 1433 … … 1209 1439 * Device tree rwlock should be held at least for reading. 1210 1440 * 1441 * @param tree Device tree 1211 1442 * @param parent The parent function node. 1212 1443 * @param name The name of the child function. 1213 1444 * @return The child function node. 1214 1445 */ 1215 fun_node_t *find_node_child(fun_node_t *pfun, const char *name) 1216 { 1217 return find_fun_node_in_device(pfun->child, name); 1446 static fun_node_t *find_node_child(dev_tree_t *tree, fun_node_t *pfun, 1447 const char *name) 1448 { 1449 return find_fun_node_in_device(tree, pfun->child, name); 1218 1450 } 1219 1451 … … 1228 1460 fibril_rwlock_read_lock(&tree->rwlock); 1229 1461 link = hash_table_find(&tree->loc_functions, &key); 1230 if (link != NULL) 1462 if (link != NULL) { 1231 1463 fun = hash_table_get_instance(link, fun_node_t, loc_fun); 1464 fun_add_ref(fun); 1465 } 1232 1466 fibril_rwlock_read_unlock(&tree->rwlock); 1233 1467 … … 1237 1471 void tree_add_loc_function(dev_tree_t *tree, fun_node_t *fun) 1238 1472 { 1473 assert(fibril_rwlock_is_write_locked(&tree->rwlock)); 1474 1239 1475 unsigned long key = (unsigned long) fun->service_id; 1240 fibril_rwlock_write_lock(&tree->rwlock);1241 1476 hash_table_insert(&tree->loc_functions, &key, &fun->loc_fun); 1242 fibril_rwlock_write_unlock(&tree->rwlock);1243 1477 } 1244 1478 -
uspace/srv/devman/devman.h
r7a72ce1a ra1b7e80 118 118 } driver_list_t; 119 119 120 /** The state of the device.*/120 /** Device state */ 121 121 typedef enum { 122 122 DEVICE_NOT_INITIALIZED = 0, 123 123 DEVICE_USABLE, 124 124 DEVICE_NOT_PRESENT, 125 DEVICE_INVALID 125 DEVICE_INVALID, 126 /** Device node has been removed from the tree */ 127 DEVICE_REMOVED 126 128 } device_state_t; 127 129 128 130 /** Device node in the device tree. */ 129 131 struct dev_node { 132 /** Reference count */ 133 atomic_t refcnt; 134 130 135 /** The global unique identifier of the device. */ 131 136 devman_handle_t handle; … … 154 159 }; 155 160 161 /** Function state */ 162 typedef enum { 163 FUN_INIT = 0, 164 FUN_OFF_LINE, 165 FUN_ON_LINE, 166 /** Function node has been removed from the tree */ 167 FUN_REMOVED 168 } fun_state_t; 169 156 170 /** Function node in the device tree. */ 157 171 struct fun_node { 172 /** Reference count */ 173 atomic_t refcnt; 174 /** State */ 175 fun_state_t state; 176 158 177 /** The global unique identifier of the function */ 159 178 devman_handle_t handle; … … 239 258 240 259 extern void add_driver(driver_list_t *, driver_t *); 241 extern void attach_driver(dev_node_t *, driver_t *); 260 extern void attach_driver(dev_tree_t *, dev_node_t *, driver_t *); 261 extern void detach_driver(dev_tree_t *, dev_node_t *); 242 262 extern void add_device(driver_t *, dev_node_t *, dev_tree_t *); 243 263 extern bool start_driver(driver_t *); 264 extern int driver_dev_remove(dev_tree_t *, dev_node_t *); 265 extern int driver_fun_online(dev_tree_t *, fun_node_t *); 266 extern int driver_fun_offline(dev_tree_t *, fun_node_t *); 244 267 245 268 extern driver_t *find_driver(driver_list_t *, const char *); … … 254 277 extern dev_node_t *create_dev_node(void); 255 278 extern void delete_dev_node(dev_node_t *node); 279 extern void dev_add_ref(dev_node_t *); 280 extern void dev_del_ref(dev_node_t *); 256 281 extern dev_node_t *find_dev_node_no_lock(dev_tree_t *tree, 257 282 devman_handle_t handle); … … 263 288 extern fun_node_t *create_fun_node(void); 264 289 extern void delete_fun_node(fun_node_t *); 290 extern void fun_add_ref(fun_node_t *); 291 extern void fun_del_ref(fun_node_t *); 265 292 extern fun_node_t *find_fun_node_no_lock(dev_tree_t *tree, 266 293 devman_handle_t handle); 267 294 extern fun_node_t *find_fun_node(dev_tree_t *tree, devman_handle_t handle); 268 295 extern fun_node_t *find_fun_node_by_path(dev_tree_t *, char *); 269 extern fun_node_t *find_fun_node_in_device(dev_node_t *, const char *); 296 extern fun_node_t *find_fun_node_in_device(dev_tree_t *tree, dev_node_t *, 297 const char *); 270 298 271 299 /* Device tree */ … … 274 302 extern bool create_root_nodes(dev_tree_t *); 275 303 extern bool insert_dev_node(dev_tree_t *, dev_node_t *, fun_node_t *); 304 extern void remove_dev_node(dev_tree_t *, dev_node_t *); 276 305 extern bool insert_fun_node(dev_tree_t *, fun_node_t *, char *, dev_node_t *); 277 306 extern void remove_fun_node(dev_tree_t *, fun_node_t *); -
uspace/srv/devman/main.c
r7a72ce1a ra1b7e80 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 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); 336 337 } 337 338 } 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 */ 360 static 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; 339 435 } 340 436 … … 356 452 async_answer_0(callid, rc); 357 453 return; 358 } 454 } 359 455 360 456 fun_node_t *fun = find_fun_node(&device_tree, handle); 361 457 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); 362 467 async_answer_0(callid, ENOENT); 363 468 return; … … 375 480 fun->pathname, cat_name); 376 481 482 fibril_rwlock_read_unlock(&device_tree.rwlock); 483 fun_del_ref(fun); 484 377 485 async_answer_0(callid, EOK); 486 } 487 488 /** Online function by driver request. 489 * 490 */ 491 static 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 */ 531 static 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); 378 560 } 379 561 … … 385 567 int rc; 386 568 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 387 576 fibril_rwlock_write_lock(&tree->rwlock); 388 577 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) { 391 582 fibril_rwlock_write_unlock(&tree->rwlock); 392 583 async_answer_0(callid, ENOENT); … … 394 585 } 395 586 396 log_msg(LVL_DEBUG, "devman_remove_function(fun='%s')", fun->pathname);397 398 587 if (fun->ftype == fun_inner) { 399 588 /* 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 } 403 594 } 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 } 411 606 } 412 607 } … … 414 609 remove_fun_node(&device_tree, fun); 415 610 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); 417 616 418 617 log_msg(LVL_DEBUG, "devman_remove_function() succeeded."); … … 485 684 devman_add_function_to_cat(callid, &call); 486 685 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; 487 692 case DEVMAN_REMOVE_FUNCTION: 488 693 devman_remove_function(callid, &call); 489 694 break; 490 695 default: 491 async_answer_0(callid, EINVAL); 696 async_answer_0(callid, EINVAL); 492 697 break; 493 698 } … … 500 705 { 501 706 char *pathname; 707 devman_handle_t handle; 502 708 503 709 int rc = async_data_write_accept((void **) &pathname, true, 0, 0, 0, 0); … … 516 722 } 517 723 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); 519 740 } 520 741 … … 534 755 if (!async_data_read_receive(&data_callid, &data_len)) { 535 756 async_answer_0(iid, EINVAL); 757 fun_del_ref(fun); 536 758 return; 537 759 } … … 541 763 async_answer_0(data_callid, ENOMEM); 542 764 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); 543 779 return; 544 780 } … … 552 788 async_answer_0(iid, EOK); 553 789 790 fibril_rwlock_read_unlock(&device_tree.rwlock); 791 fun_del_ref(fun); 554 792 free(buffer); 555 793 } … … 571 809 if (!async_data_read_receive(&data_callid, &data_len)) { 572 810 async_answer_0(iid, EINVAL); 811 fun_del_ref(fun); 573 812 return; 574 813 } … … 578 817 async_answer_0(data_callid, ENOMEM); 579 818 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 583 836 size_t sent_length = str_size(fun->pathname); 584 837 if (sent_length > data_len) { … … 589 842 async_answer_0(iid, EOK); 590 843 844 fibril_rwlock_read_unlock(&device_tree.rwlock); 845 fun_del_ref(fun); 591 846 free(buffer); 592 847 } … … 609 864 dev_node_t *dev = find_dev_node_no_lock(&device_tree, 610 865 IPC_GET_ARG1(*icall)); 611 if (dev == NULL ) {866 if (dev == NULL || dev->state == DEVICE_REMOVED) { 612 867 fibril_rwlock_read_unlock(&device_tree.rwlock); 613 868 async_answer_0(callid, ENOENT); … … 648 903 fibril_rwlock_read_lock(&device_tree.rwlock); 649 904 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 */ 929 static void devman_fun_online(ipc_callid_t iid, ipc_call_t *icall) 930 { 931 fun_node_t *fun; 932 int rc; 933 650 934 fun = find_fun_node(&device_tree, IPC_GET_ARG1(*icall)); 651 935 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 */ 954 static 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); 666 969 } 667 970 … … 678 981 } 679 982 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 680 992 async_answer_1(iid, EOK, fun->handle); 993 fibril_rwlock_read_unlock(&device_tree.rwlock); 994 fun_del_ref(fun); 681 995 } 682 996 … … 710 1024 devman_fun_get_path(callid, &call); 711 1025 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; 712 1032 case DEVMAN_FUN_SID_TO_HANDLE: 713 1033 devman_fun_sid_to_handle(callid, &call); … … 730 1050 if (fun == NULL) 731 1051 dev = find_dev_node(&device_tree, handle); 732 else 1052 else { 1053 fibril_rwlock_read_lock(&device_tree.rwlock); 733 1054 dev = fun->dev; 1055 if (dev != NULL) 1056 dev_add_ref(dev); 1057 fibril_rwlock_read_unlock(&device_tree.rwlock); 1058 } 734 1059 735 1060 /* … … 743 1068 "function with handle %" PRIun " was found.", handle); 744 1069 async_answer_0(iid, ENOENT); 745 return;1070 goto cleanup; 746 1071 } 747 1072 … … 751 1076 handle); 752 1077 async_answer_0(iid, ENOENT); 753 return;1078 goto cleanup; 754 1079 } 755 1080 756 1081 driver_t *driver = NULL; 1082 1083 fibril_rwlock_read_lock(&device_tree.rwlock); 757 1084 758 1085 if (drv_to_parent) { … … 769 1096 } 770 1097 1098 fibril_rwlock_read_unlock(&device_tree.rwlock); 1099 771 1100 if (driver == NULL) { 772 1101 log_msg(LVL_ERROR, "IPC forwarding refused - " \ 773 1102 "the device %" PRIun " is not in usable state.", handle); 774 1103 async_answer_0(iid, ENOENT); 775 return;1104 goto cleanup; 776 1105 } 777 1106 … … 786 1115 "Could not forward to driver `%s'.", driver->name); 787 1116 async_answer_0(iid, EINVAL); 788 return;1117 goto cleanup; 789 1118 } 790 1119 … … 802 1131 async_forward_fast(iid, exch, method, fwd_h, 0, IPC_FF_NONE); 803 1132 async_exchange_end(exch); 1133 1134 cleanup: 1135 if (dev != NULL) 1136 dev_del_ref(dev); 1137 if (fun != NULL) 1138 fun_del_ref(fun); 804 1139 } 805 1140 … … 811 1146 fun_node_t *fun; 812 1147 dev_node_t *dev; 1148 devman_handle_t handle; 1149 driver_t *driver; 813 1150 814 1151 fun = find_loc_tree_function(&device_tree, service_id); 815 1152 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) { 817 1156 log_msg(LVL_WARN, "devman_connection_loc(): function " 818 1157 "not found.\n"); 1158 fibril_rwlock_read_unlock(&device_tree.rwlock); 819 1159 async_answer_0(iid, ENOENT); 820 1160 return; … … 822 1162 823 1163 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, 827 1171 IPC_FF_NONE); 828 1172 async_exchange_end(exch); … … 830 1174 log_msg(LVL_DEBUG, 831 1175 "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); 833 1179 } 834 1180 -
uspace/srv/loc/loc.c
r7a72ce1a ra1b7e80 1231 1231 svc = loc_service_find_id(svc_id); 1232 1232 1233 if (cat == NULL || svc == NULL) { 1234 fibril_mutex_unlock(&cdir.mutex); 1235 fibril_mutex_unlock(&services_list_mutex); 1236 async_answer_0(iid, ENOENT); 1237 return; 1238 } 1239 1233 1240 fibril_mutex_lock(&cat->mutex); 1234 1241 retval = category_add_service(cat, svc);
Note:
See TracChangeset
for help on using the changeset viewer.