0001
0002
0003
0004
0005
0006
0007
0008
0009 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0010
0011 #define CREATE_TRACE_POINTS
0012 #include <linux/greybus.h>
0013 #include "greybus_trace.h"
0014
0015 #define GB_BUNDLE_AUTOSUSPEND_MS 3000
0016
0017
0018 static bool nogreybus;
0019 #ifdef MODULE
0020 module_param(nogreybus, bool, 0444);
0021 #else
0022 core_param(nogreybus, nogreybus, bool, 0444);
0023 #endif
0024 int greybus_disabled(void)
0025 {
0026 return nogreybus;
0027 }
0028 EXPORT_SYMBOL_GPL(greybus_disabled);
0029
0030 static bool greybus_match_one_id(struct gb_bundle *bundle,
0031 const struct greybus_bundle_id *id)
0032 {
0033 if ((id->match_flags & GREYBUS_ID_MATCH_VENDOR) &&
0034 (id->vendor != bundle->intf->vendor_id))
0035 return false;
0036
0037 if ((id->match_flags & GREYBUS_ID_MATCH_PRODUCT) &&
0038 (id->product != bundle->intf->product_id))
0039 return false;
0040
0041 if ((id->match_flags & GREYBUS_ID_MATCH_CLASS) &&
0042 (id->class != bundle->class))
0043 return false;
0044
0045 return true;
0046 }
0047
0048 static const struct greybus_bundle_id *
0049 greybus_match_id(struct gb_bundle *bundle, const struct greybus_bundle_id *id)
0050 {
0051 if (!id)
0052 return NULL;
0053
0054 for (; id->vendor || id->product || id->class || id->driver_info;
0055 id++) {
0056 if (greybus_match_one_id(bundle, id))
0057 return id;
0058 }
0059
0060 return NULL;
0061 }
0062
0063 static int greybus_match_device(struct device *dev, struct device_driver *drv)
0064 {
0065 struct greybus_driver *driver = to_greybus_driver(drv);
0066 struct gb_bundle *bundle;
0067 const struct greybus_bundle_id *id;
0068
0069 if (!is_gb_bundle(dev))
0070 return 0;
0071
0072 bundle = to_gb_bundle(dev);
0073
0074 id = greybus_match_id(bundle, driver->id_table);
0075 if (id)
0076 return 1;
0077
0078 return 0;
0079 }
0080
0081 static int greybus_uevent(struct device *dev, struct kobj_uevent_env *env)
0082 {
0083 struct gb_host_device *hd;
0084 struct gb_module *module = NULL;
0085 struct gb_interface *intf = NULL;
0086 struct gb_control *control = NULL;
0087 struct gb_bundle *bundle = NULL;
0088 struct gb_svc *svc = NULL;
0089
0090 if (is_gb_host_device(dev)) {
0091 hd = to_gb_host_device(dev);
0092 } else if (is_gb_module(dev)) {
0093 module = to_gb_module(dev);
0094 hd = module->hd;
0095 } else if (is_gb_interface(dev)) {
0096 intf = to_gb_interface(dev);
0097 module = intf->module;
0098 hd = intf->hd;
0099 } else if (is_gb_control(dev)) {
0100 control = to_gb_control(dev);
0101 intf = control->intf;
0102 module = intf->module;
0103 hd = intf->hd;
0104 } else if (is_gb_bundle(dev)) {
0105 bundle = to_gb_bundle(dev);
0106 intf = bundle->intf;
0107 module = intf->module;
0108 hd = intf->hd;
0109 } else if (is_gb_svc(dev)) {
0110 svc = to_gb_svc(dev);
0111 hd = svc->hd;
0112 } else {
0113 dev_WARN(dev, "uevent for unknown greybus device \"type\"!\n");
0114 return -EINVAL;
0115 }
0116
0117 if (add_uevent_var(env, "BUS=%u", hd->bus_id))
0118 return -ENOMEM;
0119
0120 if (module) {
0121 if (add_uevent_var(env, "MODULE=%u", module->module_id))
0122 return -ENOMEM;
0123 }
0124
0125 if (intf) {
0126 if (add_uevent_var(env, "INTERFACE=%u", intf->interface_id))
0127 return -ENOMEM;
0128 if (add_uevent_var(env, "GREYBUS_ID=%08x/%08x",
0129 intf->vendor_id, intf->product_id))
0130 return -ENOMEM;
0131 }
0132
0133 if (bundle) {
0134
0135
0136
0137
0138
0139 if (add_uevent_var(env, "BUNDLE=%u", bundle->id))
0140 return -ENOMEM;
0141 if (add_uevent_var(env, "BUNDLE_CLASS=%02x", bundle->class))
0142 return -ENOMEM;
0143 }
0144
0145 return 0;
0146 }
0147
0148 static void greybus_shutdown(struct device *dev)
0149 {
0150 if (is_gb_host_device(dev)) {
0151 struct gb_host_device *hd;
0152
0153 hd = to_gb_host_device(dev);
0154 gb_hd_shutdown(hd);
0155 }
0156 }
0157
0158 struct bus_type greybus_bus_type = {
0159 .name = "greybus",
0160 .match = greybus_match_device,
0161 .uevent = greybus_uevent,
0162 .shutdown = greybus_shutdown,
0163 };
0164
0165 static int greybus_probe(struct device *dev)
0166 {
0167 struct greybus_driver *driver = to_greybus_driver(dev->driver);
0168 struct gb_bundle *bundle = to_gb_bundle(dev);
0169 const struct greybus_bundle_id *id;
0170 int retval;
0171
0172
0173 id = greybus_match_id(bundle, driver->id_table);
0174 if (!id)
0175 return -ENODEV;
0176
0177 retval = pm_runtime_get_sync(&bundle->intf->dev);
0178 if (retval < 0) {
0179 pm_runtime_put_noidle(&bundle->intf->dev);
0180 return retval;
0181 }
0182
0183 retval = gb_control_bundle_activate(bundle->intf->control, bundle->id);
0184 if (retval) {
0185 pm_runtime_put(&bundle->intf->dev);
0186 return retval;
0187 }
0188
0189
0190
0191
0192
0193
0194
0195
0196 pm_runtime_set_autosuspend_delay(dev, GB_BUNDLE_AUTOSUSPEND_MS);
0197 pm_runtime_use_autosuspend(dev);
0198 pm_runtime_get_noresume(dev);
0199 pm_runtime_set_active(dev);
0200 pm_runtime_enable(dev);
0201
0202 retval = driver->probe(bundle, id);
0203 if (retval) {
0204
0205
0206
0207 WARN_ON(!list_empty(&bundle->connections));
0208
0209 gb_control_bundle_deactivate(bundle->intf->control, bundle->id);
0210
0211 pm_runtime_disable(dev);
0212 pm_runtime_set_suspended(dev);
0213 pm_runtime_put_noidle(dev);
0214 pm_runtime_dont_use_autosuspend(dev);
0215 pm_runtime_put(&bundle->intf->dev);
0216
0217 return retval;
0218 }
0219
0220 pm_runtime_put(&bundle->intf->dev);
0221
0222 return 0;
0223 }
0224
0225 static int greybus_remove(struct device *dev)
0226 {
0227 struct greybus_driver *driver = to_greybus_driver(dev->driver);
0228 struct gb_bundle *bundle = to_gb_bundle(dev);
0229 struct gb_connection *connection;
0230 int retval;
0231
0232 retval = pm_runtime_get_sync(dev);
0233 if (retval < 0)
0234 dev_err(dev, "failed to resume bundle: %d\n", retval);
0235
0236
0237
0238
0239
0240
0241 list_for_each_entry(connection, &bundle->connections, bundle_links) {
0242 if (gb_connection_is_offloaded(connection))
0243 continue;
0244
0245 if (bundle->intf->disconnected)
0246 gb_connection_disable_forced(connection);
0247 else
0248 gb_connection_disable_rx(connection);
0249 }
0250
0251 driver->disconnect(bundle);
0252
0253
0254 WARN_ON(!list_empty(&bundle->connections));
0255
0256 if (!bundle->intf->disconnected)
0257 gb_control_bundle_deactivate(bundle->intf->control, bundle->id);
0258
0259 pm_runtime_put_noidle(dev);
0260 pm_runtime_disable(dev);
0261 pm_runtime_set_suspended(dev);
0262 pm_runtime_dont_use_autosuspend(dev);
0263 pm_runtime_put_noidle(dev);
0264
0265 return 0;
0266 }
0267
0268 int greybus_register_driver(struct greybus_driver *driver, struct module *owner,
0269 const char *mod_name)
0270 {
0271 int retval;
0272
0273 if (greybus_disabled())
0274 return -ENODEV;
0275
0276 driver->driver.bus = &greybus_bus_type;
0277 driver->driver.name = driver->name;
0278 driver->driver.probe = greybus_probe;
0279 driver->driver.remove = greybus_remove;
0280 driver->driver.owner = owner;
0281 driver->driver.mod_name = mod_name;
0282
0283 retval = driver_register(&driver->driver);
0284 if (retval)
0285 return retval;
0286
0287 pr_info("registered new driver %s\n", driver->name);
0288 return 0;
0289 }
0290 EXPORT_SYMBOL_GPL(greybus_register_driver);
0291
0292 void greybus_deregister_driver(struct greybus_driver *driver)
0293 {
0294 driver_unregister(&driver->driver);
0295 }
0296 EXPORT_SYMBOL_GPL(greybus_deregister_driver);
0297
0298 static int __init gb_init(void)
0299 {
0300 int retval;
0301
0302 if (greybus_disabled())
0303 return -ENODEV;
0304
0305 BUILD_BUG_ON(CPORT_ID_MAX >= (long)CPORT_ID_BAD);
0306
0307 gb_debugfs_init();
0308
0309 retval = bus_register(&greybus_bus_type);
0310 if (retval) {
0311 pr_err("bus_register failed (%d)\n", retval);
0312 goto error_bus;
0313 }
0314
0315 retval = gb_hd_init();
0316 if (retval) {
0317 pr_err("gb_hd_init failed (%d)\n", retval);
0318 goto error_hd;
0319 }
0320
0321 retval = gb_operation_init();
0322 if (retval) {
0323 pr_err("gb_operation_init failed (%d)\n", retval);
0324 goto error_operation;
0325 }
0326 return 0;
0327
0328 error_operation:
0329 gb_hd_exit();
0330 error_hd:
0331 bus_unregister(&greybus_bus_type);
0332 error_bus:
0333 gb_debugfs_cleanup();
0334
0335 return retval;
0336 }
0337 module_init(gb_init);
0338
0339 static void __exit gb_exit(void)
0340 {
0341 gb_operation_exit();
0342 gb_hd_exit();
0343 bus_unregister(&greybus_bus_type);
0344 gb_debugfs_cleanup();
0345 tracepoint_synchronize_unregister();
0346 }
0347 module_exit(gb_exit);
0348 MODULE_LICENSE("GPL v2");
0349 MODULE_AUTHOR("Greg Kroah-Hartman <gregkh@linuxfoundation.org>");