* @brief Helper function for implementing BUS_RELEASE_RESOURCE() * * Implement BUS_RELEASE_RESOURCE() using a resource list. Normally * used with resource_list_alloc(). * * @param rl the resource list which was allocated from * @param bus the parent device of @p child * @param child the device which is requesting a release * @param type the type of resource to release * @param rid th
| 3479 | * error condition prevented the operation |
| 3480 | */ |
| 3481 | int |
| 3482 | resource_list_release(struct resource_list *rl, device_t bus, device_t child, |
| 3483 | int type, int rid, struct resource *res) |
| 3484 | { |
| 3485 | struct resource_list_entry *rle = NULL; |
| 3486 | int passthrough = (device_get_parent(child) != bus); |
| 3487 | int error; |
| 3488 | |
| 3489 | if (passthrough) { |
| 3490 | return (BUS_RELEASE_RESOURCE(device_get_parent(bus), child, |
| 3491 | type, rid, res)); |
| 3492 | } |
| 3493 | |
| 3494 | rle = resource_list_find(rl, type, rid); |
| 3495 | |
| 3496 | if (!rle) |
| 3497 | panic("resource_list_release: can't find resource"); |
| 3498 | if (!rle->res) |
| 3499 | panic("resource_list_release: resource entry is not busy"); |
| 3500 | if (rle->flags & RLE_RESERVED) { |
| 3501 | if (rle->flags & RLE_ALLOCATED) { |
| 3502 | if (rman_get_flags(res) & RF_ACTIVE) { |
| 3503 | error = bus_deactivate_resource(child, type, |
| 3504 | rid, res); |
| 3505 | if (error) |
| 3506 | return (error); |
| 3507 | } |
| 3508 | rle->flags &= ~RLE_ALLOCATED; |
| 3509 | return (0); |
| 3510 | } |
| 3511 | return (EINVAL); |
| 3512 | } |
| 3513 | |
| 3514 | error = BUS_RELEASE_RESOURCE(device_get_parent(bus), child, |
| 3515 | type, rid, res); |
| 3516 | if (error) |
| 3517 | return (error); |
| 3518 | |
| 3519 | rle->res = NULL; |
| 3520 | return (0); |
| 3521 | } |
| 3522 | |
| 3523 | /** |
| 3524 | * @brief Release all active resources of a given type |
no test coverage detected