cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

module.c (5062B)


      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}