root/drivers/greybus/bundle.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. bundle_class_show
  2. bundle_id_show
  3. state_show
  4. state_store
  5. gb_bundle_find
  6. gb_bundle_release
  7. gb_bundle_disable_all_connections
  8. gb_bundle_enable_all_connections
  9. gb_bundle_suspend
  10. gb_bundle_resume
  11. gb_bundle_idle
  12. gb_bundle_create
  13. gb_bundle_add
  14. gb_bundle_destroy

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * Greybus bundles
   4  *
   5  * Copyright 2014-2015 Google Inc.
   6  * Copyright 2014-2015 Linaro Ltd.
   7  */
   8 
   9 #include <linux/greybus.h>
  10 #include "greybus_trace.h"
  11 
  12 static ssize_t bundle_class_show(struct device *dev,
  13                                  struct device_attribute *attr, char *buf)
  14 {
  15         struct gb_bundle *bundle = to_gb_bundle(dev);
  16 
  17         return sprintf(buf, "0x%02x\n", bundle->class);
  18 }
  19 static DEVICE_ATTR_RO(bundle_class);
  20 
  21 static ssize_t bundle_id_show(struct device *dev,
  22                               struct device_attribute *attr, char *buf)
  23 {
  24         struct gb_bundle *bundle = to_gb_bundle(dev);
  25 
  26         return sprintf(buf, "%u\n", bundle->id);
  27 }
  28 static DEVICE_ATTR_RO(bundle_id);
  29 
  30 static ssize_t state_show(struct device *dev, struct device_attribute *attr,
  31                           char *buf)
  32 {
  33         struct gb_bundle *bundle = to_gb_bundle(dev);
  34 
  35         if (!bundle->state)
  36                 return sprintf(buf, "\n");
  37 
  38         return sprintf(buf, "%s\n", bundle->state);
  39 }
  40 
  41 static ssize_t state_store(struct device *dev, struct device_attribute *attr,
  42                            const char *buf, size_t size)
  43 {
  44         struct gb_bundle *bundle = to_gb_bundle(dev);
  45 
  46         kfree(bundle->state);
  47         bundle->state = kstrdup(buf, GFP_KERNEL);
  48         if (!bundle->state)
  49                 return -ENOMEM;
  50 
  51         /* Tell userspace that the file contents changed */
  52         sysfs_notify(&bundle->dev.kobj, NULL, "state");
  53 
  54         return size;
  55 }
  56 static DEVICE_ATTR_RW(state);
  57 
  58 static struct attribute *bundle_attrs[] = {
  59         &dev_attr_bundle_class.attr,
  60         &dev_attr_bundle_id.attr,
  61         &dev_attr_state.attr,
  62         NULL,
  63 };
  64 
  65 ATTRIBUTE_GROUPS(bundle);
  66 
  67 static struct gb_bundle *gb_bundle_find(struct gb_interface *intf,
  68                                         u8 bundle_id)
  69 {
  70         struct gb_bundle *bundle;
  71 
  72         list_for_each_entry(bundle, &intf->bundles, links) {
  73                 if (bundle->id == bundle_id)
  74                         return bundle;
  75         }
  76 
  77         return NULL;
  78 }
  79 
  80 static void gb_bundle_release(struct device *dev)
  81 {
  82         struct gb_bundle *bundle = to_gb_bundle(dev);
  83 
  84         trace_gb_bundle_release(bundle);
  85 
  86         kfree(bundle->state);
  87         kfree(bundle->cport_desc);
  88         kfree(bundle);
  89 }
  90 
  91 #ifdef CONFIG_PM
  92 static void gb_bundle_disable_all_connections(struct gb_bundle *bundle)
  93 {
  94         struct gb_connection *connection;
  95 
  96         list_for_each_entry(connection, &bundle->connections, bundle_links)
  97                 gb_connection_disable(connection);
  98 }
  99 
 100 static void gb_bundle_enable_all_connections(struct gb_bundle *bundle)
 101 {
 102         struct gb_connection *connection;
 103 
 104         list_for_each_entry(connection, &bundle->connections, bundle_links)
 105                 gb_connection_enable(connection);
 106 }
 107 
 108 static int gb_bundle_suspend(struct device *dev)
 109 {
 110         struct gb_bundle *bundle = to_gb_bundle(dev);
 111         const struct dev_pm_ops *pm = dev->driver->pm;
 112         int ret;
 113 
 114         if (pm && pm->runtime_suspend) {
 115                 ret = pm->runtime_suspend(&bundle->dev);
 116                 if (ret)
 117                         return ret;
 118         } else {
 119                 gb_bundle_disable_all_connections(bundle);
 120         }
 121 
 122         ret = gb_control_bundle_suspend(bundle->intf->control, bundle->id);
 123         if (ret) {
 124                 if (pm && pm->runtime_resume)
 125                         ret = pm->runtime_resume(dev);
 126                 else
 127                         gb_bundle_enable_all_connections(bundle);
 128 
 129                 return ret;
 130         }
 131 
 132         return 0;
 133 }
 134 
 135 static int gb_bundle_resume(struct device *dev)
 136 {
 137         struct gb_bundle *bundle = to_gb_bundle(dev);
 138         const struct dev_pm_ops *pm = dev->driver->pm;
 139         int ret;
 140 
 141         ret = gb_control_bundle_resume(bundle->intf->control, bundle->id);
 142         if (ret)
 143                 return ret;
 144 
 145         if (pm && pm->runtime_resume) {
 146                 ret = pm->runtime_resume(dev);
 147                 if (ret)
 148                         return ret;
 149         } else {
 150                 gb_bundle_enable_all_connections(bundle);
 151         }
 152 
 153         return 0;
 154 }
 155 
 156 static int gb_bundle_idle(struct device *dev)
 157 {
 158         pm_runtime_mark_last_busy(dev);
 159         pm_request_autosuspend(dev);
 160 
 161         return 0;
 162 }
 163 #endif
 164 
 165 static const struct dev_pm_ops gb_bundle_pm_ops = {
 166         SET_RUNTIME_PM_OPS(gb_bundle_suspend, gb_bundle_resume, gb_bundle_idle)
 167 };
 168 
 169 struct device_type greybus_bundle_type = {
 170         .name =         "greybus_bundle",
 171         .release =      gb_bundle_release,
 172         .pm =           &gb_bundle_pm_ops,
 173 };
 174 
 175 /*
 176  * Create a gb_bundle structure to represent a discovered
 177  * bundle.  Returns a pointer to the new bundle or a null
 178  * pointer if a failure occurs due to memory exhaustion.
 179  */
 180 struct gb_bundle *gb_bundle_create(struct gb_interface *intf, u8 bundle_id,
 181                                    u8 class)
 182 {
 183         struct gb_bundle *bundle;
 184 
 185         if (bundle_id == BUNDLE_ID_NONE) {
 186                 dev_err(&intf->dev, "can't use bundle id %u\n", bundle_id);
 187                 return NULL;
 188         }
 189 
 190         /*
 191          * Reject any attempt to reuse a bundle id.  We initialize
 192          * these serially, so there's no need to worry about keeping
 193          * the interface bundle list locked here.
 194          */
 195         if (gb_bundle_find(intf, bundle_id)) {
 196                 dev_err(&intf->dev, "duplicate bundle id %u\n", bundle_id);
 197                 return NULL;
 198         }
 199 
 200         bundle = kzalloc(sizeof(*bundle), GFP_KERNEL);
 201         if (!bundle)
 202                 return NULL;
 203 
 204         bundle->intf = intf;
 205         bundle->id = bundle_id;
 206         bundle->class = class;
 207         INIT_LIST_HEAD(&bundle->connections);
 208 
 209         bundle->dev.parent = &intf->dev;
 210         bundle->dev.bus = &greybus_bus_type;
 211         bundle->dev.type = &greybus_bundle_type;
 212         bundle->dev.groups = bundle_groups;
 213         bundle->dev.dma_mask = intf->dev.dma_mask;
 214         device_initialize(&bundle->dev);
 215         dev_set_name(&bundle->dev, "%s.%d", dev_name(&intf->dev), bundle_id);
 216 
 217         list_add(&bundle->links, &intf->bundles);
 218 
 219         trace_gb_bundle_create(bundle);
 220 
 221         return bundle;
 222 }
 223 
 224 int gb_bundle_add(struct gb_bundle *bundle)
 225 {
 226         int ret;
 227 
 228         ret = device_add(&bundle->dev);
 229         if (ret) {
 230                 dev_err(&bundle->dev, "failed to register bundle: %d\n", ret);
 231                 return ret;
 232         }
 233 
 234         trace_gb_bundle_add(bundle);
 235 
 236         return 0;
 237 }
 238 
 239 /*
 240  * Tear down a previously set up bundle.
 241  */
 242 void gb_bundle_destroy(struct gb_bundle *bundle)
 243 {
 244         trace_gb_bundle_destroy(bundle);
 245 
 246         if (device_is_registered(&bundle->dev))
 247                 device_del(&bundle->dev);
 248 
 249         list_del(&bundle->links);
 250 
 251         put_device(&bundle->dev);
 252 }

/* [<][>][^][v][top][bottom][index][help] */