Changeset 80a96d2 in mainline
- Timestamp:
- 2011-09-05T21:26:47Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- b33870b
- Parents:
- 16cc9a6
- Location:
- uspace
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/test/test1/test1.c
r16cc9a6 r80a96d2 42 42 static int test1_add_device(ddf_dev_t *dev); 43 43 static int test1_dev_remove(ddf_dev_t *dev); 44 static int test1_dev_gone(ddf_dev_t *dev); 44 45 static int test1_fun_online(ddf_fun_t *fun); 45 46 static int test1_fun_offline(ddf_fun_t *fun); … … 48 49 .add_device = &test1_add_device, 49 50 .dev_remove = &test1_dev_remove, 51 .dev_gone = &test1_dev_gone, 50 52 .fun_online = &test1_fun_online, 51 53 .fun_offline = &test1_fun_offline … … 213 215 } 214 216 217 static int fun_unbind(ddf_fun_t *fun, const char *name) 218 { 219 int rc; 220 221 ddf_msg(LVL_DEBUG, "fun_unbind(%p, '%s')", fun, name); 222 rc = ddf_fun_unbind(fun); 223 if (rc != EOK) { 224 ddf_msg(LVL_ERROR, "Failed unbinding function '%s'.", name); 225 return rc; 226 } 227 228 ddf_fun_destroy(fun); 229 return EOK; 230 } 231 215 232 static int test1_dev_remove(ddf_dev_t *dev) 216 233 { … … 234 251 if (test1->child != NULL) { 235 252 rc = fun_remove(test1->child, "child"); 253 if (rc != EOK) 254 return rc; 255 } 256 257 return EOK; 258 } 259 260 static int test1_dev_gone(ddf_dev_t *dev) 261 { 262 test1_t *test1 = (test1_t *)dev->driver_data; 263 int rc; 264 265 ddf_msg(LVL_DEBUG, "test1_dev_remove(%p)", dev); 266 267 if (test1->fun_a != NULL) { 268 rc = fun_unbind(test1->fun_a, "a"); 269 if (rc != EOK) 270 return rc; 271 } 272 273 if (test1->clone != NULL) { 274 rc = fun_unbind(test1->clone, "clone"); 275 if (rc != EOK) 276 return rc; 277 } 278 279 if (test1->child != NULL) { 280 rc = fun_unbind(test1->child, "child"); 236 281 if (rc != EOK) 237 282 return rc; -
uspace/drv/test/test2/test2.c
r16cc9a6 r80a96d2 42 42 static int test2_add_device(ddf_dev_t *dev); 43 43 static int test2_dev_remove(ddf_dev_t *dev); 44 static int test2_dev_gone(ddf_dev_t *dev); 44 45 static int test2_fun_online(ddf_fun_t *fun); 45 46 static int test2_fun_offline(ddf_fun_t *fun); … … 48 49 .add_device = &test2_add_device, 49 50 .dev_remove = &test2_dev_remove, 51 .dev_gone = &test2_dev_gone, 50 52 .fun_online = &test2_fun_online, 51 53 .fun_offline = &test2_fun_offline … … 111 113 } 112 114 113 /** Add child devices after some sleep.115 /** Simulate plugging and surprise unplugging. 114 116 * 115 117 * @param arg Parent device structure (ddf_dev_t *). 116 118 * @return Always EOK. 117 119 */ 118 static int p ostponed_birth(void *arg)120 static int plug_unplug(void *arg) 119 121 { 120 122 test2_t *test2 = (test2_t *) arg; … … 144 146 test2->fun_a = fun_a; 145 147 148 async_usleep(10000000); 149 150 ddf_msg(LVL_NOTE, "Unbinding function test1."); 151 ddf_fun_unbind(test2->test1); 152 async_usleep(1000000); 153 ddf_msg(LVL_NOTE, "Unbinding function child."); 154 ddf_fun_unbind(test2->child); 155 146 156 return EOK; 147 157 } … … 158 168 } 159 169 170 rc = ddf_fun_unbind(fun); 171 if (rc != EOK) { 172 ddf_msg(LVL_ERROR, "Failed unbinding function '%s'.", name); 173 return rc; 174 } 175 176 ddf_fun_destroy(fun); 177 return EOK; 178 } 179 180 static int fun_unbind(ddf_fun_t *fun, const char *name) 181 { 182 int rc; 183 184 ddf_msg(LVL_DEBUG, "fun_unbind(%p, '%s')", fun, name); 160 185 rc = ddf_fun_unbind(fun); 161 186 if (rc != EOK) { … … 184 209 185 210 if (str_cmp(dev->name, "child") != 0) { 186 fid_t postpone = fibril_create(p ostponed_birth, test2);211 fid_t postpone = fibril_create(plug_unplug, test2); 187 212 if (postpone == 0) { 188 213 ddf_msg(LVL_ERROR, "fibril_create() failed."); … … 232 257 } 233 258 259 static int test2_dev_gone(ddf_dev_t *dev) 260 { 261 test2_t *test2 = (test2_t *)dev->driver_data; 262 int rc; 263 264 ddf_msg(LVL_DEBUG, "test2_dev_gone(%p)", dev); 265 266 if (test2->fun_a != NULL) { 267 rc = fun_unbind(test2->fun_a, "a"); 268 if (rc != EOK) 269 return rc; 270 } 271 272 if (test2->fun_err != NULL) { 273 rc = fun_unbind(test2->fun_err, "ERROR"); 274 if (rc != EOK) 275 return rc; 276 } 277 278 if (test2->child != NULL) { 279 rc = fun_unbind(test2->child, "child"); 280 if (rc != EOK) 281 return rc; 282 } 283 284 if (test2->test1 != NULL) { 285 rc = fun_unbind(test2->test1, "test1"); 286 if (rc != EOK) 287 return rc; 288 } 289 290 return EOK; 291 } 292 234 293 235 294 static int test2_fun_online(ddf_fun_t *fun) … … 248 307 { 249 308 printf(NAME ": HelenOS test2 virtual device driver\n"); 250 ddf_log_init(NAME, LVL_ ERROR);309 ddf_log_init(NAME, LVL_NOTE); 251 310 return ddf_driver_main(&test2_driver); 252 311 } -
uspace/lib/c/include/ipc/devman.h
r16cc9a6 r80a96d2 147 147 DRIVER_DEV_ADD = IPC_FIRST_USER_METHOD, 148 148 DRIVER_DEV_REMOVE, 149 DRIVER_DEV_GONE, 149 150 DRIVER_FUN_ONLINE, 150 151 DRIVER_FUN_OFFLINE, 151 152 152 } devman_to_driver_t; 153 153 -
uspace/lib/drv/generic/driver.c
r16cc9a6 r80a96d2 333 333 } 334 334 335 static void driver_dev_gone(ipc_callid_t iid, ipc_call_t *icall) 336 { 337 devman_handle_t devh; 338 ddf_dev_t *dev; 339 int rc; 340 341 devh = IPC_GET_ARG1(*icall); 342 343 fibril_mutex_lock(&devices_mutex); 344 dev = driver_get_device(devh); 345 if (dev != NULL) 346 dev_add_ref(dev); 347 fibril_mutex_unlock(&devices_mutex); 348 349 if (dev == NULL) { 350 async_answer_0(iid, ENOENT); 351 return; 352 } 353 354 if (driver->driver_ops->dev_gone != NULL) 355 rc = driver->driver_ops->dev_gone(dev); 356 else 357 rc = ENOTSUP; 358 359 if (rc == EOK) 360 dev_del_ref(dev); 361 362 async_answer_0(iid, (sysarg_t) rc); 363 } 364 335 365 static void driver_fun_online(ipc_callid_t iid, ipc_call_t *icall) 336 366 { … … 423 453 case DRIVER_DEV_REMOVE: 424 454 driver_dev_remove(callid, &call); 455 break; 456 case DRIVER_DEV_GONE: 457 driver_dev_gone(callid, &call); 425 458 break; 426 459 case DRIVER_FUN_ONLINE: -
uspace/lib/drv/include/ddf/driver.h
r16cc9a6 r80a96d2 139 139 /** Ask driver to remove a device */ 140 140 int (*dev_remove)(ddf_dev_t *); 141 /** Inform driver a device disappeared */ 142 int (*dev_gone)(ddf_dev_t *); 141 143 /** Ask driver to online a specific function */ 142 144 int (*fun_online)(ddf_fun_t *); -
uspace/srv/devman/devman.c
r16cc9a6 r80a96d2 878 878 879 879 return retval; 880 880 } 881 882 int driver_dev_gone(dev_tree_t *tree, dev_node_t *dev) 883 { 884 async_exch_t *exch; 885 sysarg_t retval; 886 driver_t *drv; 887 devman_handle_t handle; 888 889 assert(dev != NULL); 890 891 log_msg(LVL_DEBUG, "driver_dev_gone(%p)", dev); 892 893 fibril_rwlock_read_lock(&tree->rwlock); 894 drv = dev->drv; 895 handle = dev->handle; 896 fibril_rwlock_read_unlock(&tree->rwlock); 897 898 exch = async_exchange_begin(drv->sess); 899 retval = async_req_1_0(exch, DRIVER_DEV_GONE, handle); 900 async_exchange_end(exch); 901 902 return retval; 881 903 } 882 904 -
uspace/srv/devman/devman.h
r16cc9a6 r80a96d2 263 263 extern bool start_driver(driver_t *); 264 264 extern int driver_dev_remove(dev_tree_t *, dev_node_t *); 265 extern int driver_dev_gone(dev_tree_t *, dev_node_t *); 265 266 extern int driver_fun_online(dev_tree_t *, fun_node_t *); 266 267 extern int driver_fun_offline(dev_tree_t *, fun_node_t *); -
uspace/srv/devman/main.c
r16cc9a6 r80a96d2 316 316 if (fun->child != NULL) { 317 317 dev_node_t *dev = fun->child; 318 device_state_t dev_state; 318 319 319 320 dev_add_ref(dev); 321 dev_state = dev->state; 322 320 323 fibril_rwlock_write_unlock(&device_tree.rwlock); 321 324 322 325 /* If device is owned by driver, ask driver to give it up. */ 323 if (dev ->state == DEVICE_USABLE) {326 if (dev_state == DEVICE_USABLE) { 324 327 rc = driver_dev_remove(&device_tree, dev); 325 328 if (rc != EOK) { … … 333 336 if (!list_empty(&dev->functions)) { 334 337 fibril_rwlock_read_unlock(&device_tree.rwlock); 338 dev_del_ref(dev); 335 339 return EIO; 336 340 } 341 337 342 driver_t *driver = dev->drv; 338 343 fibril_rwlock_read_unlock(&device_tree.rwlock); … … 579 584 int rc; 580 585 581 582 586 fun_node_t *fun = find_fun_node(&device_tree, fun_handle); 583 587 if (fun == NULL) { … … 598 602 599 603 if (fun->ftype == fun_inner) { 600 /* Handle possible descendants */ 601 /* TODO - This is a surprise removal */ 604 /* This is a surprise removal. Handle possible descendants */ 602 605 if (fun->child != NULL) { 603 log_msg(LVL_WARN, "devman_remove_function(): not handling " 604 "descendants\n"); 606 dev_node_t *dev = fun->child; 607 device_state_t dev_state; 608 int gone_rc; 609 610 dev_add_ref(dev); 611 dev_state = dev->state; 612 613 fibril_rwlock_write_unlock(&device_tree.rwlock); 614 615 /* If device is owned by driver, inform driver it is gone. */ 616 if (dev_state == DEVICE_USABLE) 617 gone_rc = driver_dev_gone(&device_tree, dev); 618 else 619 gone_rc = EOK; 620 621 fibril_rwlock_read_lock(&device_tree.rwlock); 622 623 /* Verify that driver succeeded and removed all functions */ 624 if (gone_rc != EOK || !list_empty(&dev->functions)) { 625 log_msg(LVL_ERROR, "Driver did not remove " 626 "functions for device that is gone. " 627 "Device node is now defunct."); 628 629 /* 630 * Not much we can do but mark the device 631 * node as having invalid state. This 632 * is a driver bug. 633 */ 634 dev->state = DEVICE_INVALID; 635 fibril_rwlock_read_unlock(&device_tree.rwlock); 636 dev_del_ref(dev); 637 return; 638 } 639 640 driver_t *driver = dev->drv; 641 fibril_rwlock_read_unlock(&device_tree.rwlock); 642 643 if (driver) 644 detach_driver(&device_tree, dev); 645 646 fibril_rwlock_write_lock(&device_tree.rwlock); 647 remove_dev_node(&device_tree, dev); 648 649 /* Delete ref created when node was inserted */ 650 dev_del_ref(dev); 651 /* Delete ref created by dev_add_ref(dev) above */ 652 dev_del_ref(dev); 605 653 } 606 654 } else {
Note:
See TracChangeset
for help on using the changeset viewer.