linux/drivers/greybus/module.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Greybus Module code
   4 *
   5 * Copyright 2016 Google Inc.
   6 * Copyright 2016 Linaro Ltd.
   7 */
   8
   9#include <linux/greybus.h>
  10#include "greybus_trace.h"
  11
  12static ssize_t eject_store(struct device *dev,
  13                           struct device_attribute *attr,
  14                           const char *buf, size_t len)
  15{
  16        struct gb_module *module = to_gb_module(dev);
  17        struct gb_interface *intf;
  18        size_t i;
  19        long val;
  20        int ret;
  21
  22        ret = kstrtol(buf, 0, &val);
  23        if (ret)
  24                return ret;
  25
  26        if (!val)
  27                return len;
  28
  29        for (i = 0; i < module->num_interfaces; ++i) {
  30                intf = module->interfaces[i];
  31
  32                mutex_lock(&intf->mutex);
  33                /* Set flag to prevent concurrent activation. */
  34                intf->ejected = true;
  35                gb_interface_disable(intf);
  36                gb_interface_deactivate(intf);
  37                mutex_unlock(&intf->mutex);
  38        }
  39
  40        /* Tell the SVC to eject the primary interface. */
  41        ret = gb_svc_intf_eject(module->hd->svc, module->module_id);
  42        if (ret)
  43                return ret;
  44
  45        return len;
  46}
  47static DEVICE_ATTR_WO(eject);
  48
  49static ssize_t module_id_show(struct device *dev,
  50                              struct device_attribute *attr, char *buf)
  51{
  52        struct gb_module *module = to_gb_module(dev);
  53
  54        return sprintf(buf, "%u\n", module->module_id);
  55}
  56static DEVICE_ATTR_RO(module_id);
  57
  58static ssize_t num_interfaces_show(struct device *dev,
  59                                   struct device_attribute *attr, char *buf)
  60{
  61        struct gb_module *module = to_gb_module(dev);
  62
  63        return sprintf(buf, "%zu\n", module->num_interfaces);
  64}
  65static DEVICE_ATTR_RO(num_interfaces);
  66
  67static struct attribute *module_attrs[] = {
  68        &dev_attr_eject.attr,
  69        &dev_attr_module_id.attr,
  70        &dev_attr_num_interfaces.attr,
  71        NULL,
  72};
  73ATTRIBUTE_GROUPS(module);
  74
  75static void gb_module_release(struct device *dev)
  76{
  77        struct gb_module *module = to_gb_module(dev);
  78
  79        trace_gb_module_release(module);
  80
  81        kfree(module);
  82}
  83
  84struct device_type greybus_module_type = {
  85        .name           = "greybus_module",
  86        .release        = gb_module_release,
  87};
  88
  89struct gb_module *gb_module_create(struct gb_host_device *hd, u8 module_id,
  90                                   size_t num_interfaces)
  91{
  92        struct gb_interface *intf;
  93        struct gb_module *module;
  94        int i;
  95
  96        module = kzalloc(struct_size(module, interfaces, num_interfaces),
  97                         GFP_KERNEL);
  98        if (!module)
  99                return NULL;
 100
 101        module->hd = hd;
 102        module->module_id = module_id;
 103        module->num_interfaces = num_interfaces;
 104
 105        module->dev.parent = &hd->dev;
 106        module->dev.bus = &greybus_bus_type;
 107        module->dev.type = &greybus_module_type;
 108        module->dev.groups = module_groups;
 109        module->dev.dma_mask = hd->dev.dma_mask;
 110        device_initialize(&module->dev);
 111        dev_set_name(&module->dev, "%d-%u", hd->bus_id, module_id);
 112
 113        trace_gb_module_create(module);
 114
 115        for (i = 0; i < num_interfaces; ++i) {
 116                intf = gb_interface_create(module, module_id + i);
 117                if (!intf) {
 118                        dev_err(&module->dev, "failed to create interface %u\n",
 119                                module_id + i);
 120                        goto err_put_interfaces;
 121                }
 122                module->interfaces[i] = intf;
 123        }
 124
 125        return module;
 126
 127err_put_interfaces:
 128        for (--i; i >= 0; --i)
 129                gb_interface_put(module->interfaces[i]);
 130
 131        put_device(&module->dev);
 132
 133        return NULL;
 134}
 135
 136/*
 137 * Register and enable an interface after first attempting to activate it.
 138 */
 139static void gb_module_register_interface(struct gb_interface *intf)
 140{
 141        struct gb_module *module = intf->module;
 142        u8 intf_id = intf->interface_id;
 143        int ret;
 144
 145        mutex_lock(&intf->mutex);
 146
 147        ret = gb_interface_activate(intf);
 148        if (ret) {
 149                if (intf->type != GB_INTERFACE_TYPE_DUMMY) {
 150                        dev_err(&module->dev,
 151                                "failed to activate interface %u: %d\n",
 152                                intf_id, ret);
 153                }
 154
 155                gb_interface_add(intf);
 156                goto err_unlock;
 157        }
 158
 159        ret = gb_interface_add(intf);
 160        if (ret)
 161                goto err_interface_deactivate;
 162
 163        ret = gb_interface_enable(intf);
 164        if (ret) {
 165                dev_err(&module->dev, "failed to enable interface %u: %d\n",
 166                        intf_id, ret);
 167                goto err_interface_deactivate;
 168        }
 169
 170        mutex_unlock(&intf->mutex);
 171
 172        return;
 173
 174err_interface_deactivate:
 175        gb_interface_deactivate(intf);
 176err_unlock:
 177        mutex_unlock(&intf->mutex);
 178}
 179
 180static void gb_module_deregister_interface(struct gb_interface *intf)
 181{
 182        /* Mark as disconnected to prevent I/O during disable. */
 183        if (intf->module->disconnected)
 184                intf->disconnected = true;
 185
 186        mutex_lock(&intf->mutex);
 187        intf->removed = true;
 188        gb_interface_disable(intf);
 189        gb_interface_deactivate(intf);
 190        mutex_unlock(&intf->mutex);
 191
 192        gb_interface_del(intf);
 193}
 194
 195/* Register a module and its interfaces. */
 196int gb_module_add(struct gb_module *module)
 197{
 198        size_t i;
 199        int ret;
 200
 201        ret = device_add(&module->dev);
 202        if (ret) {
 203                dev_err(&module->dev, "failed to register module: %d\n", ret);
 204                return ret;
 205        }
 206
 207        trace_gb_module_add(module);
 208
 209        for (i = 0; i < module->num_interfaces; ++i)
 210                gb_module_register_interface(module->interfaces[i]);
 211
 212        return 0;
 213}
 214
 215/* Deregister a module and its interfaces. */
 216void gb_module_del(struct gb_module *module)
 217{
 218        size_t i;
 219
 220        for (i = 0; i < module->num_interfaces; ++i)
 221                gb_module_deregister_interface(module->interfaces[i]);
 222
 223        trace_gb_module_del(module);
 224
 225        device_del(&module->dev);
 226}
 227
 228void gb_module_put(struct gb_module *module)
 229{
 230        size_t i;
 231
 232        for (i = 0; i < module->num_interfaces; ++i)
 233                gb_interface_put(module->interfaces[i]);
 234
 235        put_device(&module->dev);
 236}
 237