brintos

brintos / linux-shallow public Read only

0
0
Text · 4.9 KiB · 7f7153a Raw
237 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Greybus Module code4 *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 84const struct 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