Ignore:
Timestamp:
2011-09-03T13:37:16Z (13 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
8ff0bd2, a9abe5fc
Parents:
b29bb09
Message:

rootvirt removal support.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/infrastructure/rootvirt/rootvirt.c

    rb29bb09 rdeac215e  
    6363
    6464static int rootvirt_add_device(ddf_dev_t *dev);
     65static int rootvirt_dev_remove(ddf_dev_t *dev);
    6566static int rootvirt_fun_online(ddf_fun_t *fun);
    6667static int rootvirt_fun_offline(ddf_fun_t *fun);
     
    6869static driver_ops_t rootvirt_ops = {
    6970        .add_device = &rootvirt_add_device,
     71        .dev_remove = &rootvirt_dev_remove,
    7072        .fun_online = &rootvirt_fun_online,
    7173        .fun_offline = &rootvirt_fun_offline
     
    7779};
    7880
     81/* Device soft state */
     82typedef struct {
     83        ddf_dev_t *dev;
     84        list_t functions;
     85} rootvirt_t;
     86
     87/* Function soft state */
     88typedef struct {
     89        ddf_fun_t *fun;
     90        link_t dev_link;
     91} rootvirt_fun_t;
     92
     93static int instances = 0;
     94
     95
    7996/** Add function to the virtual device.
    8097 *
     
    83100 * @return              EOK on success or negative error code.
    84101 */
    85 static int rootvirt_add_fun(ddf_dev_t *vdev, virtual_function_t *vfun)
    86 {
     102static int rootvirt_add_fun(rootvirt_t *rootvirt, virtual_function_t *vfun)
     103{
     104        ddf_dev_t *vdev = rootvirt->dev;
    87105        ddf_fun_t *fun;
     106        rootvirt_fun_t *rvfun;
    88107        int rc;
    89108
     
    97116        }
    98117
     118        rvfun = ddf_fun_data_alloc(fun, sizeof(rootvirt_fun_t));
     119        if (rvfun == NULL) {
     120                ddf_msg(LVL_ERROR, "Failed allocating soft state for %s.",
     121                    vfun->name);
     122                ddf_fun_destroy(fun);
     123                return ENOMEM;
     124        }
     125
     126        rvfun->fun = fun;
     127
    99128        rc = ddf_fun_add_match_id(fun, vfun->match_id, 10);
    100129        if (rc != EOK) {
     
    113142        }
    114143
     144        list_append(&rvfun->dev_link, &rootvirt->functions);
     145
    115146        ddf_msg(LVL_NOTE, "Registered child device `%s'", vfun->name);
    116147        return EOK;
    117148}
    118149
     150static int rootvirt_fun_remove(rootvirt_fun_t *rvfun)
     151{
     152        int rc;
     153        const char *name = rvfun->fun->name;
     154
     155        ddf_msg(LVL_DEBUG, "rootvirt_fun_remove('%s')", name);
     156        rc = ddf_fun_offline(rvfun->fun);
     157        if (rc != EOK) {
     158                ddf_msg(LVL_ERROR, "Error offlining function '%s'.", name);
     159                return rc;
     160        }
     161
     162        rc = ddf_fun_unbind(rvfun->fun);
     163        if (rc != EOK) {
     164                ddf_msg(LVL_ERROR, "Failed unbinding function '%s'.", name);
     165                return rc;
     166        }
     167
     168        list_remove(&rvfun->dev_link);
     169        ddf_fun_destroy(rvfun->fun);
     170        return EOK;
     171}
     172
     173
    119174static int rootvirt_add_device(ddf_dev_t *dev)
    120175{
    121         static int instances = 0;
     176        rootvirt_t *rootvirt;
    122177
    123178        /*
    124179         * Allow only single instance of root virtual device.
    125180         */
    126         instances++;
    127         if (instances > 1) {
     181        if (++instances > 1) {
    128182                return ELIMIT;
    129183        }
    130184
    131185        ddf_msg(LVL_DEBUG, "add_device(handle=%d)", (int)dev->handle);
     186
     187        rootvirt = ddf_dev_data_alloc(dev, sizeof(rootvirt_t));
     188        if (rootvirt == NULL)
     189                return ENOMEM;
     190
     191        rootvirt->dev = dev;
     192        list_initialize(&rootvirt->functions);
    132193
    133194        /*
     
    137198        virtual_function_t *vfun = virtual_functions;
    138199        while (vfun->name != NULL) {
    139                 (void) rootvirt_add_fun(dev, vfun);
     200                (void) rootvirt_add_fun(rootvirt, vfun);
    140201                vfun++;
    141202        }
    142203
     204        return EOK;
     205}
     206
     207static int rootvirt_dev_remove(ddf_dev_t *dev)
     208{
     209        rootvirt_t *rootvirt = (rootvirt_t *)dev->driver_data;
     210        int rc;
     211
     212        while (!list_empty(&rootvirt->functions)) {
     213                rootvirt_fun_t *rvfun = list_get_instance(
     214                    list_first(&rootvirt->functions), rootvirt_fun_t,
     215                        dev_link);
     216
     217                rc = rootvirt_fun_remove(rvfun);
     218                if (rc != EOK)
     219                        return rc;
     220        }
     221
     222        --instances;
    143223        return EOK;
    144224}
Note: See TracChangeset for help on using the changeset viewer.