Changeset 8300c72 in mainline for uspace/srv/devman


Ignore:
Timestamp:
2025-03-03T22:58:05Z (7 months ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
master
Children:
77a0119
Parents:
f35749e
Message:

Quiesce devices before proceeding with shutdown.

Only implemented for e1k, uhci and xhci.

Location:
uspace/srv/devman
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/devman/client_conn.c

    rf35749e r8300c72  
    11/*
     2 * Copyright (c) 2025 Jiri Svoboda
    23 * Copyright (c) 2010 Lenka Trochtova
    3  * Copyright (c) 2013 Jiri Svoboda
    44 * All rights reserved.
    55 *
     
    479479}
    480480
     481/** Quiesce function.
     482 *
     483 * Send a request to quiesce a function to the responsible driver.
     484 */
     485static void devman_fun_quiesce(ipc_call_t *icall)
     486{
     487        fun_node_t *fun;
     488        dev_node_t *child;
     489        errno_t rc;
     490
     491        fun = find_fun_node(&device_tree, ipc_get_arg1(icall));
     492        if (fun == NULL) {
     493                async_answer_0(icall, ENOENT);
     494                return;
     495        }
     496
     497        fibril_rwlock_read_lock(&device_tree.rwlock);
     498
     499        /* Check function state */
     500        if (fun->state == FUN_REMOVED) {
     501                fibril_rwlock_read_unlock(&device_tree.rwlock);
     502                async_answer_0(icall, ENOENT);
     503                return;
     504        }
     505
     506        child = fun->child;
     507        dev_add_ref(child);
     508        fibril_rwlock_read_unlock(&device_tree.rwlock);
     509
     510        rc = driver_dev_quiesce(&device_tree, child);
     511        fun_del_ref(fun);
     512
     513        async_answer_0(icall, rc);
     514}
     515
    481516/** Find handle for the function instance identified by its service ID. */
    482517static void devman_fun_sid_to_handle(ipc_call_t *icall)
     
    790825                        devman_fun_offline(&call);
    791826                        break;
     827                case DEVMAN_FUN_QUIESCE:
     828                        devman_fun_quiesce(&call);
     829                        break;
    792830                case DEVMAN_FUN_SID_TO_HANDLE:
    793831                        devman_fun_sid_to_handle(&call);
  • uspace/srv/devman/driver.c

    rf35749e r8300c72  
    741741}
    742742
     743errno_t driver_dev_quiesce(dev_tree_t *tree, dev_node_t *dev)
     744{
     745        async_exch_t *exch;
     746        errno_t retval;
     747        driver_t *drv;
     748        devman_handle_t handle;
     749
     750        assert(dev != NULL);
     751
     752        log_msg(LOG_DEFAULT, LVL_DEBUG, "driver_dev_quiesce(%p)", dev);
     753
     754        fibril_rwlock_read_lock(&tree->rwlock);
     755        drv = dev->drv;
     756        handle = dev->handle;
     757        fibril_rwlock_read_unlock(&tree->rwlock);
     758
     759        exch = async_exchange_begin(drv->sess);
     760        retval = async_req_1_0(exch, DRIVER_DEV_QUIESCE, handle);
     761        async_exchange_end(exch);
     762
     763        return retval;
     764}
     765
    743766errno_t driver_dev_gone(dev_tree_t *tree, dev_node_t *dev)
    744767{
  • uspace/srv/devman/driver.h

    rf35749e r8300c72  
    11/*
     2 * Copyright (c) 2025 Jiri Svoboda
    23 * Copyright (c) 2010 Lenka Trochtova
    3  * Copyright (c) 2013 Jiri Svoboda
    44 * All rights reserved.
    55 *
     
    5353extern void add_device(driver_t *, dev_node_t *, dev_tree_t *);
    5454extern errno_t driver_dev_remove(dev_tree_t *, dev_node_t *);
     55extern errno_t driver_dev_quiesce(dev_tree_t *, dev_node_t *);
    5556extern errno_t driver_dev_gone(dev_tree_t *, dev_node_t *);
    5657extern errno_t driver_fun_online(dev_tree_t *, fun_node_t *);
  • uspace/srv/devman/drv_conn.c

    rf35749e r8300c72  
    444444
    445445        rc = fun_offline(fun);
     446        if (rc != EOK) {
     447                fun_busy_unlock(fun);
     448                fun_del_ref(fun);
     449                async_answer_0(icall, rc);
     450                return;
     451        }
     452
     453        fun_busy_unlock(fun);
     454        fun_del_ref(fun);
     455        async_answer_0(icall, EOK);
     456}
     457
     458/** Quiesce function by driver request.
     459 *
     460 */
     461static void devman_drv_fun_quiesce(ipc_call_t *icall, driver_t *drv)
     462{
     463        fun_node_t *fun;
     464        errno_t rc;
     465
     466        fun = find_fun_node(&device_tree, ipc_get_arg1(icall));
     467        if (fun == NULL) {
     468                async_answer_0(icall, ENOENT);
     469                return;
     470        }
     471
     472        fun_busy_lock(fun);
     473
     474        fibril_rwlock_write_lock(&device_tree.rwlock);
     475        if (fun->dev == NULL || fun->dev->drv != drv) {
     476                fun_busy_unlock(fun);
     477                fun_del_ref(fun);
     478                async_answer_0(icall, ENOENT);
     479                return;
     480        }
     481        fibril_rwlock_write_unlock(&device_tree.rwlock);
     482
     483        rc = fun_quiesce(fun);
    446484        if (rc != EOK) {
    447485                fun_busy_unlock(fun);
     
    677715                        devman_drv_fun_offline(&call, driver);
    678716                        break;
     717                case DEVMAN_DRV_FUN_QUIESCE:
     718                        devman_drv_fun_quiesce(&call, driver);
     719                        break;
    679720                case DEVMAN_DRV_FUN_WAIT_STABLE:
    680721                        devman_drv_fun_wait_stable(&call, driver);
  • uspace/srv/devman/fun.c

    rf35749e r8300c72  
    11/*
     2 * Copyright (c) 2025 Jiri Svoboda
    23 * Copyright (c) 2010 Lenka Trochtova
    34 * All rights reserved.
     
    428429}
    429430
     431errno_t fun_quiesce(fun_node_t *fun)
     432{
     433        errno_t rc;
     434
     435        log_msg(LOG_DEFAULT, LVL_DEBUG, "fun_quiesce(%s)", fun->pathname);
     436        fibril_rwlock_read_lock(&device_tree.rwlock);
     437
     438        if (fun->state == FUN_OFF_LINE) {
     439                fibril_rwlock_read_unlock(&device_tree.rwlock);
     440                log_msg(LOG_DEFAULT, LVL_DEBUG, "Function %s is off line.",
     441                    fun->pathname);
     442                return EOK;
     443        }
     444
     445        if (fun->ftype != fun_inner) {
     446                /* Nothing to do */
     447                log_msg(LOG_DEFAULT, LVL_DEBUG, "Nothing to do for external "
     448                    "function %s\n", fun->pathname);
     449                fibril_rwlock_read_unlock(&device_tree.rwlock);
     450                return EOK;
     451        }
     452
     453        log_msg(LOG_DEFAULT, LVL_DEBUG, "Quiescing inner function %s.",
     454            fun->pathname);
     455
     456        if (fun->child == NULL) {
     457                log_msg(LOG_DEFAULT, LVL_DEBUG, "Function %s child is NULL.",
     458                    fun->pathname);
     459                fibril_rwlock_read_unlock(&device_tree.rwlock);
     460                return EOK;
     461        }
     462
     463        dev_node_t *dev = fun->child;
     464        device_state_t dev_state;
     465
     466        dev_add_ref(dev);
     467        dev_state = dev->state;
     468
     469        fibril_rwlock_read_unlock(&device_tree.rwlock);
     470
     471        /* If device is owned by driver, ask driver to quiesce it. */
     472        if (dev_state == DEVICE_USABLE) {
     473                log_msg(LOG_DEFAULT, LVL_DEBUG, "Call driver_dev_quiesce() "
     474                    "for %s.", fun->pathname);
     475                rc = driver_dev_quiesce(&device_tree, dev);
     476                if (rc != EOK) {
     477                        log_msg(LOG_DEFAULT, LVL_ERROR,
     478                            "driver_dev_quiesce() -> %d", (int)rc);
     479                        dev_del_ref(dev);
     480                        return ENOTSUP;
     481                }
     482        }
     483
     484        dev_del_ref(dev);
     485        return EOK;
     486}
     487
    430488/** @}
    431489 */
  • uspace/srv/devman/fun.h

    rf35749e r8300c72  
    11/*
     2 * Copyright (c) 2025 Jiri Svoboda
    23 * Copyright (c) 2010 Lenka Trochtova
    3  * Copyright (c) 2013 Jiri Svoboda
    44 * All rights reserved.
    55 *
     
    5151extern errno_t fun_online(fun_node_t *);
    5252extern errno_t fun_offline(fun_node_t *);
     53extern errno_t fun_quiesce(fun_node_t *);
    5354
    5455#endif
Note: See TracChangeset for help on using the changeset viewer.