Linux Audio

Check our new training course

Linux BSP development engineering services

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