Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset 81685dd9 in mainline


Ignore:
Timestamp:
2017-10-20T07:18:57Z (3 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
master
Children:
feab36ae
Parents:
04efacc
Message:

Add devctl unload-drv subcommand to manually unload a driver that is not in use.

Location:
uspace
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/devctl/devctl.c

    r04efacc r81685dd9  
    337337}
    338338
     339static int drv_unload(const char *drvname)
     340{
     341        int rc;
     342        devman_handle_t drvh;
     343
     344        rc = devman_driver_get_handle(drvname, &drvh);
     345        if (rc != EOK) {
     346                printf("Failed resolving driver '%s' (%d).\n", drvname, rc);
     347                return rc;
     348        }
     349
     350        rc = devman_driver_unload(drvh);
     351        if (rc != EOK) {
     352                printf("Failed unloading driver '%s' (%d).\n", drvname, rc);
     353                return rc;
     354        }
     355
     356        return EOK;
     357}
     358
    339359static void print_syntax(void)
    340360{
     
    346366        printf("\tdevctl show-drv <driver-name>\n");
    347367        printf("\tdevctl load-drv <driver-name>\n");
     368        printf("\tdevctl unload-drv <driver-name>\n");
    348369}
    349370
     
    412433                if (rc != EOK)
    413434                        return 2;
     435        } else if (str_cmp(argv[1], "unload-drv") == 0) {
     436                if (argc < 3) {
     437                        printf(NAME ": Argument missing.\n");
     438                        print_syntax();
     439                        return 1;
     440                }
     441
     442                rc = drv_unload(argv[2]);
     443                if (rc != EOK)
     444                        return 2;
    414445        } else {
    415446                printf(NAME ": Invalid argument '%s'.\n", argv[1]);
  • uspace/lib/c/generic/devman.c

    r04efacc r81685dd9  
    719719}
    720720
     721int devman_driver_unload(devman_handle_t drvh)
     722{
     723        async_exch_t *exch = devman_exchange_begin(INTERFACE_DDF_CLIENT);
     724        if (exch == NULL)
     725                return ENOMEM;
     726       
     727        int rc = async_req_1_0(exch, DEVMAN_DRIVER_UNLOAD, drvh);
     728       
     729        devman_exchange_end(exch);
     730        return rc;
     731}
     732
    721733/** @}
    722734 */
  • uspace/lib/c/include/devman.h

    r04efacc r81685dd9  
    8282extern int devman_driver_get_state(devman_handle_t, driver_state_t *);
    8383extern int devman_driver_load(devman_handle_t);
     84extern int devman_driver_unload(devman_handle_t);
    8485
    8586#endif
  • uspace/lib/c/include/ipc/devman.h

    r04efacc r81685dd9  
    156156        DRIVER_FUN_ONLINE,
    157157        DRIVER_FUN_OFFLINE,
     158        DRIVER_STOP
    158159} devman_to_driver_t;
    159160
     
    176177        DEVMAN_DRIVER_GET_NAME,
    177178        DEVMAN_DRIVER_GET_STATE,
    178         DEVMAN_DRIVER_LOAD
     179        DEVMAN_DRIVER_LOAD,
     180        DEVMAN_DRIVER_UNLOAD
    179181} client_to_devman_t;
    180182
  • uspace/lib/drv/generic/driver.c

    r04efacc r81685dd9  
    6868FIBRIL_MUTEX_INITIALIZE(functions_mutex);
    6969
     70FIBRIL_RWLOCK_INITIALIZE(stopping_lock);
     71static bool stopping = false;
     72
    7073static ddf_dev_t *create_device(void);
    7174static void delete_device(ddf_dev_t *);
     
    127130        }
    128131       
     132        fibril_rwlock_read_lock(&stopping_lock);
     133
     134        if (stopping) {
     135                fibril_rwlock_read_unlock(&stopping_lock);
     136                async_answer_0(iid, EIO);
     137                return;
     138        }
     139       
    129140        ddf_dev_t *dev = create_device();
    130141        if (!dev) {
     142                fibril_rwlock_read_unlock(&stopping_lock);
    131143                free(dev_name);
    132144                async_answer_0(iid, ENOMEM);
     
    148160       
    149161        if (res != EOK) {
     162                fibril_rwlock_read_unlock(&stopping_lock);
    150163                dev_del_ref(dev);
    151164                async_answer_0(iid, res);
     
    156169        list_append(&dev->link, &devices);
    157170        fibril_mutex_unlock(&devices_mutex);
     171        fibril_rwlock_read_unlock(&stopping_lock);
    158172       
    159173        async_answer_0(iid, res);
     
    282296       
    283297        async_answer_0(iid, (sysarg_t) rc);
     298}
     299
     300static void driver_stop(ipc_callid_t iid, ipc_call_t *icall)
     301{
     302        /* Prevent new devices from being added */
     303        fibril_rwlock_write_lock(&stopping_lock);
     304        stopping = true;
     305
     306        /* Check if there are any devices */
     307        fibril_mutex_lock(&devices_mutex);
     308        if (list_first(&devices) != NULL) {
     309                /* Devices exist, roll back */
     310                fibril_mutex_unlock(&devices_mutex);
     311                stopping = false;
     312                fibril_rwlock_write_unlock(&stopping_lock);
     313                async_answer_0(iid, EBUSY);
     314                return;
     315        }
     316
     317        fibril_rwlock_write_unlock(&stopping_lock);
     318
     319        /* There should be no functions at this point */
     320        fibril_mutex_lock(&functions_mutex);
     321        assert(list_first(&functions) == NULL);
     322        fibril_mutex_unlock(&functions_mutex);
     323
     324        /* Reply with success and terminate */
     325        async_answer_0(iid, EOK);
     326        exit(0);
    284327}
    285328
     
    312355                case DRIVER_FUN_OFFLINE:
    313356                        driver_fun_offline(callid, &call);
     357                        break;
     358                case DRIVER_STOP:
     359                        driver_stop(callid, &call);
    314360                        break;
    315361                default:
  • uspace/srv/devman/client_conn.c

    r04efacc r81685dd9  
    726726}
    727727
     728/** Unload a driver by user request. */
     729static void devman_driver_unload(ipc_callid_t iid, ipc_call_t *icall)
     730{
     731        driver_t *drv;
     732        int rc;
     733       
     734        drv = driver_find(&drivers_list, IPC_GET_ARG1(*icall));
     735        if (drv == NULL) {
     736                async_answer_0(iid, ENOENT);
     737                return;
     738        }
     739       
     740        fibril_mutex_lock(&drv->driver_mutex);
     741        rc = stop_driver(drv);
     742        fibril_mutex_unlock(&drv->driver_mutex);
     743
     744        async_answer_0(iid, rc);
     745}
     746
    728747/** Function for handling connections from a client to the device manager. */
    729748void devman_connection_client(ipc_callid_t iid, ipc_call_t *icall, void *arg)
     
    794813                        devman_driver_load(callid, &call);
    795814                        break;
     815                case DEVMAN_DRIVER_UNLOAD:
     816                        devman_driver_unload(callid, &call);
     817                        break;
    796818                default:
    797819                        async_answer_0(callid, ENOENT);
  • uspace/srv/devman/driver.c

    r04efacc r81685dd9  
    298298        drv->state = DRIVER_STARTING;
    299299        return true;
     300}
     301
     302/** Stop a driver
     303 *
     304 * @param drv           The driver's structure.
     305 * @return              True if the driver's task is successfully spawned, false
     306 *                      otherwise.
     307 */
     308int stop_driver(driver_t *drv)
     309{
     310        async_exch_t *exch;
     311        sysarg_t retval;
     312       
     313        log_msg(LOG_DEFAULT, LVL_DEBUG, "stop_driver(drv=\"%s\")", drv->name);
     314
     315        exch = async_exchange_begin(drv->sess);
     316        retval = async_req_0_0(exch, DRIVER_STOP);
     317        loc_exchange_end(exch);
     318       
     319        if (retval != EOK)
     320                return retval;
     321       
     322        drv->state = DRIVER_NOT_STARTED;
     323        async_hangup(drv->sess);
     324        drv->sess = NULL;
     325        return EOK;
    300326}
    301327
  • uspace/srv/devman/driver.h

    r04efacc r81685dd9  
    5050extern void detach_driver(dev_tree_t *, dev_node_t *);
    5151extern bool start_driver(driver_t *);
     52extern int stop_driver(driver_t *);
    5253extern void add_device(driver_t *, dev_node_t *, dev_tree_t *);
    5354extern int driver_dev_remove(dev_tree_t *, dev_node_t *);
Note: See TracChangeset for help on using the changeset viewer.