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

mips_cdmm.c (19906B)


      1/*
      2 * Bus driver for MIPS Common Device Memory Map (CDMM).
      3 *
      4 * Copyright (C) 2014-2015 Imagination Technologies Ltd.
      5 *
      6 * This file is subject to the terms and conditions of the GNU General Public
      7 * License.  See the file "COPYING" in the main directory of this archive
      8 * for more details.
      9 */
     10
     11#include <linux/atomic.h>
     12#include <linux/err.h>
     13#include <linux/cpu.h>
     14#include <linux/cpumask.h>
     15#include <linux/io.h>
     16#include <linux/of_address.h>
     17#include <linux/of.h>
     18#include <linux/platform_device.h>
     19#include <linux/slab.h>
     20#include <linux/smp.h>
     21#include <asm/cdmm.h>
     22#include <asm/hazards.h>
     23#include <asm/mipsregs.h>
     24
     25/* Access control and status register fields */
     26#define CDMM_ACSR_DEVTYPE_SHIFT	24
     27#define CDMM_ACSR_DEVTYPE	(255ul << CDMM_ACSR_DEVTYPE_SHIFT)
     28#define CDMM_ACSR_DEVSIZE_SHIFT	16
     29#define CDMM_ACSR_DEVSIZE	(31ul << CDMM_ACSR_DEVSIZE_SHIFT)
     30#define CDMM_ACSR_DEVREV_SHIFT	12
     31#define CDMM_ACSR_DEVREV	(15ul << CDMM_ACSR_DEVREV_SHIFT)
     32#define CDMM_ACSR_UW		(1ul << 3)
     33#define CDMM_ACSR_UR		(1ul << 2)
     34#define CDMM_ACSR_SW		(1ul << 1)
     35#define CDMM_ACSR_SR		(1ul << 0)
     36
     37/* Each block of device registers is 64 bytes */
     38#define CDMM_DRB_SIZE		64
     39
     40#define to_mips_cdmm_driver(d)	container_of(d, struct mips_cdmm_driver, drv)
     41
     42/* Default physical base address */
     43static phys_addr_t mips_cdmm_default_base;
     44
     45/* Bus operations */
     46
     47static const struct mips_cdmm_device_id *
     48mips_cdmm_lookup(const struct mips_cdmm_device_id *table,
     49		 struct mips_cdmm_device *dev)
     50{
     51	int ret = 0;
     52
     53	for (; table->type; ++table) {
     54		ret = (dev->type == table->type);
     55		if (ret)
     56			break;
     57	}
     58
     59	return ret ? table : NULL;
     60}
     61
     62static int mips_cdmm_match(struct device *dev, struct device_driver *drv)
     63{
     64	struct mips_cdmm_device *cdev = to_mips_cdmm_device(dev);
     65	struct mips_cdmm_driver *cdrv = to_mips_cdmm_driver(drv);
     66
     67	return mips_cdmm_lookup(cdrv->id_table, cdev) != NULL;
     68}
     69
     70static int mips_cdmm_uevent(struct device *dev, struct kobj_uevent_env *env)
     71{
     72	struct mips_cdmm_device *cdev = to_mips_cdmm_device(dev);
     73	int retval = 0;
     74
     75	retval = add_uevent_var(env, "CDMM_CPU=%u", cdev->cpu);
     76	if (retval)
     77		return retval;
     78
     79	retval = add_uevent_var(env, "CDMM_TYPE=0x%02x", cdev->type);
     80	if (retval)
     81		return retval;
     82
     83	retval = add_uevent_var(env, "CDMM_REV=%u", cdev->rev);
     84	if (retval)
     85		return retval;
     86
     87	retval = add_uevent_var(env, "MODALIAS=mipscdmm:t%02X", cdev->type);
     88	return retval;
     89}
     90
     91/* Device attributes */
     92
     93#define CDMM_ATTR(name, fmt, arg...)					\
     94static ssize_t name##_show(struct device *_dev,				\
     95			   struct device_attribute *attr, char *buf)	\
     96{									\
     97	struct mips_cdmm_device *dev = to_mips_cdmm_device(_dev);	\
     98	return sprintf(buf, fmt, arg);					\
     99}									\
    100static DEVICE_ATTR_RO(name);
    101
    102CDMM_ATTR(cpu, "%u\n", dev->cpu);
    103CDMM_ATTR(type, "0x%02x\n", dev->type);
    104CDMM_ATTR(revision, "%u\n", dev->rev);
    105CDMM_ATTR(modalias, "mipscdmm:t%02X\n", dev->type);
    106CDMM_ATTR(resource, "\t%016llx\t%016llx\t%016lx\n",
    107	  (unsigned long long)dev->res.start,
    108	  (unsigned long long)dev->res.end,
    109	  dev->res.flags);
    110
    111static struct attribute *mips_cdmm_dev_attrs[] = {
    112	&dev_attr_cpu.attr,
    113	&dev_attr_type.attr,
    114	&dev_attr_revision.attr,
    115	&dev_attr_modalias.attr,
    116	&dev_attr_resource.attr,
    117	NULL,
    118};
    119ATTRIBUTE_GROUPS(mips_cdmm_dev);
    120
    121struct bus_type mips_cdmm_bustype = {
    122	.name		= "cdmm",
    123	.dev_groups	= mips_cdmm_dev_groups,
    124	.match		= mips_cdmm_match,
    125	.uevent		= mips_cdmm_uevent,
    126};
    127EXPORT_SYMBOL_GPL(mips_cdmm_bustype);
    128
    129/*
    130 * Standard driver callback helpers.
    131 *
    132 * All the CDMM driver callbacks need to be executed on the appropriate CPU from
    133 * workqueues. For the standard driver callbacks we need a work function
    134 * (mips_cdmm_{void,int}_work()) to do the actual call from the right CPU, and a
    135 * wrapper function (generated with BUILD_PERCPU_HELPER) to arrange for the work
    136 * function to be called on that CPU.
    137 */
    138
    139/**
    140 * struct mips_cdmm_work_dev - Data for per-device call work.
    141 * @fn:		CDMM driver callback function to call for the device.
    142 * @dev:	CDMM device to pass to @fn.
    143 */
    144struct mips_cdmm_work_dev {
    145	void			*fn;
    146	struct mips_cdmm_device *dev;
    147};
    148
    149/**
    150 * mips_cdmm_void_work() - Call a void returning CDMM driver callback.
    151 * @data:	struct mips_cdmm_work_dev pointer.
    152 *
    153 * A work_on_cpu() callback function to call an arbitrary CDMM driver callback
    154 * function which doesn't return a value.
    155 */
    156static long mips_cdmm_void_work(void *data)
    157{
    158	struct mips_cdmm_work_dev *work = data;
    159	void (*fn)(struct mips_cdmm_device *) = work->fn;
    160
    161	fn(work->dev);
    162	return 0;
    163}
    164
    165/**
    166 * mips_cdmm_int_work() - Call an int returning CDMM driver callback.
    167 * @data:	struct mips_cdmm_work_dev pointer.
    168 *
    169 * A work_on_cpu() callback function to call an arbitrary CDMM driver callback
    170 * function which returns an int.
    171 */
    172static long mips_cdmm_int_work(void *data)
    173{
    174	struct mips_cdmm_work_dev *work = data;
    175	int (*fn)(struct mips_cdmm_device *) = work->fn;
    176
    177	return fn(work->dev);
    178}
    179
    180#define _BUILD_RET_void
    181#define _BUILD_RET_int	return
    182
    183/**
    184 * BUILD_PERCPU_HELPER() - Helper to call a CDMM driver callback on right CPU.
    185 * @_ret:	Return type (void or int).
    186 * @_name:	Name of CDMM driver callback function.
    187 *
    188 * Generates a specific device callback function to call a CDMM driver callback
    189 * function on the appropriate CPU for the device, and if applicable return the
    190 * result.
    191 */
    192#define BUILD_PERCPU_HELPER(_ret, _name)				\
    193static _ret mips_cdmm_##_name(struct device *dev)			\
    194{									\
    195	struct mips_cdmm_device *cdev = to_mips_cdmm_device(dev);	\
    196	struct mips_cdmm_driver *cdrv = to_mips_cdmm_driver(dev->driver); \
    197	struct mips_cdmm_work_dev work = {				\
    198		.fn	= cdrv->_name,					\
    199		.dev	= cdev,						\
    200	};								\
    201									\
    202	_BUILD_RET_##_ret work_on_cpu(cdev->cpu,			\
    203				      mips_cdmm_##_ret##_work, &work);	\
    204}
    205
    206/* Driver callback functions */
    207BUILD_PERCPU_HELPER(int, probe)     /* int mips_cdmm_probe(struct device) */
    208BUILD_PERCPU_HELPER(int, remove)    /* int mips_cdmm_remove(struct device) */
    209BUILD_PERCPU_HELPER(void, shutdown) /* void mips_cdmm_shutdown(struct device) */
    210
    211
    212/* Driver registration */
    213
    214/**
    215 * mips_cdmm_driver_register() - Register a CDMM driver.
    216 * @drv:	CDMM driver information.
    217 *
    218 * Register a CDMM driver with the CDMM subsystem. The driver will be informed
    219 * of matching devices which are discovered.
    220 *
    221 * Returns:	0 on success.
    222 */
    223int mips_cdmm_driver_register(struct mips_cdmm_driver *drv)
    224{
    225	drv->drv.bus = &mips_cdmm_bustype;
    226
    227	if (drv->probe)
    228		drv->drv.probe = mips_cdmm_probe;
    229	if (drv->remove)
    230		drv->drv.remove = mips_cdmm_remove;
    231	if (drv->shutdown)
    232		drv->drv.shutdown = mips_cdmm_shutdown;
    233
    234	return driver_register(&drv->drv);
    235}
    236EXPORT_SYMBOL_GPL(mips_cdmm_driver_register);
    237
    238/**
    239 * mips_cdmm_driver_unregister() - Unregister a CDMM driver.
    240 * @drv:	CDMM driver information.
    241 *
    242 * Unregister a CDMM driver from the CDMM subsystem.
    243 */
    244void mips_cdmm_driver_unregister(struct mips_cdmm_driver *drv)
    245{
    246	driver_unregister(&drv->drv);
    247}
    248EXPORT_SYMBOL_GPL(mips_cdmm_driver_unregister);
    249
    250
    251/* CDMM initialisation and bus discovery */
    252
    253/**
    254 * struct mips_cdmm_bus - Info about CDMM bus.
    255 * @phys:		Physical address at which it is mapped.
    256 * @regs:		Virtual address where registers can be accessed.
    257 * @drbs:		Total number of DRBs.
    258 * @drbs_reserved:	Number of DRBs reserved.
    259 * @discovered:		Whether the devices on the bus have been discovered yet.
    260 * @offline:		Whether the CDMM bus is going offline (or very early
    261 *			coming back online), in which case it should be
    262 *			reconfigured each time.
    263 */
    264struct mips_cdmm_bus {
    265	phys_addr_t	 phys;
    266	void __iomem	*regs;
    267	unsigned int	 drbs;
    268	unsigned int	 drbs_reserved;
    269	bool		 discovered;
    270	bool		 offline;
    271};
    272
    273static struct mips_cdmm_bus mips_cdmm_boot_bus;
    274static DEFINE_PER_CPU(struct mips_cdmm_bus *, mips_cdmm_buses);
    275static atomic_t mips_cdmm_next_id = ATOMIC_INIT(-1);
    276
    277/**
    278 * mips_cdmm_get_bus() - Get the per-CPU CDMM bus information.
    279 *
    280 * Get information about the per-CPU CDMM bus, if the bus is present.
    281 *
    282 * The caller must prevent migration to another CPU, either by disabling
    283 * pre-emption or by running from a pinned kernel thread.
    284 *
    285 * Returns:	Pointer to CDMM bus information for the current CPU.
    286 *		May return ERR_PTR(-errno) in case of error, so check with
    287 *		IS_ERR().
    288 */
    289static struct mips_cdmm_bus *mips_cdmm_get_bus(void)
    290{
    291	struct mips_cdmm_bus *bus, **bus_p;
    292	unsigned long flags;
    293	unsigned int cpu;
    294
    295	if (!cpu_has_cdmm)
    296		return ERR_PTR(-ENODEV);
    297
    298	cpu = smp_processor_id();
    299	/* Avoid early use of per-cpu primitives before initialised */
    300	if (cpu == 0)
    301		return &mips_cdmm_boot_bus;
    302
    303	/* Get bus pointer */
    304	bus_p = per_cpu_ptr(&mips_cdmm_buses, cpu);
    305	local_irq_save(flags);
    306	bus = *bus_p;
    307	/* Attempt allocation if NULL */
    308	if (unlikely(!bus)) {
    309		bus = kzalloc(sizeof(*bus), GFP_ATOMIC);
    310		if (unlikely(!bus))
    311			bus = ERR_PTR(-ENOMEM);
    312		else
    313			*bus_p = bus;
    314	}
    315	local_irq_restore(flags);
    316	return bus;
    317}
    318
    319/**
    320 * mips_cdmm_cur_base() - Find current physical base address of CDMM region.
    321 *
    322 * Returns:	Physical base address of CDMM region according to cdmmbase CP0
    323 *		register, or 0 if the CDMM region is disabled.
    324 */
    325static phys_addr_t mips_cdmm_cur_base(void)
    326{
    327	unsigned long cdmmbase = read_c0_cdmmbase();
    328
    329	if (!(cdmmbase & MIPS_CDMMBASE_EN))
    330		return 0;
    331
    332	return (cdmmbase >> MIPS_CDMMBASE_ADDR_SHIFT)
    333		<< MIPS_CDMMBASE_ADDR_START;
    334}
    335
    336/**
    337 * mips_cdmm_phys_base() - Choose a physical base address for CDMM region.
    338 *
    339 * Picking a suitable physical address at which to map the CDMM region is
    340 * platform specific, so this weak function can be overridden by platform
    341 * code to pick a suitable value if none is configured by the bootloader.
    342 * By default this method tries to find a CDMM-specific node in the system
    343 * dtb. Note that this won't work for early serial console.
    344 */
    345phys_addr_t __weak mips_cdmm_phys_base(void)
    346{
    347	struct device_node *np;
    348	struct resource res;
    349	int err;
    350
    351	np = of_find_compatible_node(NULL, NULL, "mti,mips-cdmm");
    352	if (np) {
    353		err = of_address_to_resource(np, 0, &res);
    354		of_node_put(np);
    355		if (!err)
    356			return res.start;
    357	}
    358
    359	return 0;
    360}
    361
    362/**
    363 * mips_cdmm_setup() - Ensure the CDMM bus is initialised and usable.
    364 * @bus:	Pointer to bus information for current CPU.
    365 *		IS_ERR(bus) is checked, so no need for caller to check.
    366 *
    367 * The caller must prevent migration to another CPU, either by disabling
    368 * pre-emption or by running from a pinned kernel thread.
    369 *
    370 * Returns	0 on success, -errno on failure.
    371 */
    372static int mips_cdmm_setup(struct mips_cdmm_bus *bus)
    373{
    374	unsigned long cdmmbase, flags;
    375	int ret = 0;
    376
    377	if (IS_ERR(bus))
    378		return PTR_ERR(bus);
    379
    380	local_irq_save(flags);
    381	/* Don't set up bus a second time unless marked offline */
    382	if (bus->offline) {
    383		/* If CDMM region is still set up, nothing to do */
    384		if (bus->phys == mips_cdmm_cur_base())
    385			goto out;
    386		/*
    387		 * The CDMM region isn't set up as expected, so it needs
    388		 * reconfiguring, but then we can stop checking it.
    389		 */
    390		bus->offline = false;
    391	} else if (bus->phys > 1) {
    392		goto out;
    393	}
    394
    395	/* If the CDMM region is already configured, inherit that setup */
    396	if (!bus->phys)
    397		bus->phys = mips_cdmm_cur_base();
    398	/* Otherwise, ask platform code for suggestions */
    399	if (!bus->phys)
    400		bus->phys = mips_cdmm_phys_base();
    401	/* Otherwise, copy what other CPUs have done */
    402	if (!bus->phys)
    403		bus->phys = mips_cdmm_default_base;
    404	/* Otherwise, complain once */
    405	if (!bus->phys) {
    406		bus->phys = 1;
    407		/*
    408		 * If you hit this, either your bootloader needs to set up the
    409		 * CDMM on the boot CPU, or else you need to implement
    410		 * mips_cdmm_phys_base() for your platform (see asm/cdmm.h).
    411		 */
    412		pr_err("cdmm%u: Failed to choose a physical base\n",
    413		       smp_processor_id());
    414	}
    415	/* Already complained? */
    416	if (bus->phys == 1) {
    417		ret = -ENOMEM;
    418		goto out;
    419	}
    420	/* Record our success for other CPUs to copy */
    421	mips_cdmm_default_base = bus->phys;
    422
    423	pr_debug("cdmm%u: Enabling CDMM region at %pa\n",
    424		 smp_processor_id(), &bus->phys);
    425
    426	/* Enable CDMM */
    427	cdmmbase = read_c0_cdmmbase();
    428	cdmmbase &= (1ul << MIPS_CDMMBASE_ADDR_SHIFT) - 1;
    429	cdmmbase |= (bus->phys >> MIPS_CDMMBASE_ADDR_START)
    430			<< MIPS_CDMMBASE_ADDR_SHIFT;
    431	cdmmbase |= MIPS_CDMMBASE_EN;
    432	write_c0_cdmmbase(cdmmbase);
    433	tlbw_use_hazard();
    434
    435	bus->regs = (void __iomem *)CKSEG1ADDR(bus->phys);
    436	bus->drbs = 1 + ((cdmmbase & MIPS_CDMMBASE_SIZE) >>
    437			 MIPS_CDMMBASE_SIZE_SHIFT);
    438	bus->drbs_reserved = !!(cdmmbase & MIPS_CDMMBASE_CI);
    439
    440out:
    441	local_irq_restore(flags);
    442	return ret;
    443}
    444
    445/**
    446 * mips_cdmm_early_probe() - Minimally probe for a specific device on CDMM.
    447 * @dev_type:	CDMM type code to look for.
    448 *
    449 * Minimally configure the in-CPU Common Device Memory Map (CDMM) and look for a
    450 * specific device. This can be used to find a device very early in boot for
    451 * example to configure an early FDC console device.
    452 *
    453 * The caller must prevent migration to another CPU, either by disabling
    454 * pre-emption or by running from a pinned kernel thread.
    455 *
    456 * Returns:	MMIO pointer to device memory. The caller can read the ACSR
    457 *		register to find more information about the device (such as the
    458 *		version number or the number of blocks).
    459 *		May return IOMEM_ERR_PTR(-errno) in case of error, so check with
    460 *		IS_ERR().
    461 */
    462void __iomem *mips_cdmm_early_probe(unsigned int dev_type)
    463{
    464	struct mips_cdmm_bus *bus;
    465	void __iomem *cdmm;
    466	u32 acsr;
    467	unsigned int drb, type, size;
    468	int err;
    469
    470	if (WARN_ON(!dev_type))
    471		return IOMEM_ERR_PTR(-ENODEV);
    472
    473	bus = mips_cdmm_get_bus();
    474	err = mips_cdmm_setup(bus);
    475	if (err)
    476		return IOMEM_ERR_PTR(err);
    477
    478	/* Skip the first block if it's reserved for more registers */
    479	drb = bus->drbs_reserved;
    480	cdmm = bus->regs;
    481
    482	/* Look for a specific device type */
    483	for (; drb < bus->drbs; drb += size + 1) {
    484		acsr = __raw_readl(cdmm + drb * CDMM_DRB_SIZE);
    485		type = (acsr & CDMM_ACSR_DEVTYPE) >> CDMM_ACSR_DEVTYPE_SHIFT;
    486		if (type == dev_type)
    487			return cdmm + drb * CDMM_DRB_SIZE;
    488		size = (acsr & CDMM_ACSR_DEVSIZE) >> CDMM_ACSR_DEVSIZE_SHIFT;
    489	}
    490
    491	return IOMEM_ERR_PTR(-ENODEV);
    492}
    493EXPORT_SYMBOL_GPL(mips_cdmm_early_probe);
    494
    495/**
    496 * mips_cdmm_release() - Release a removed CDMM device.
    497 * @dev:	Device object
    498 *
    499 * Clean up the struct mips_cdmm_device for an unused CDMM device. This is
    500 * called automatically by the driver core when a device is removed.
    501 */
    502static void mips_cdmm_release(struct device *dev)
    503{
    504	struct mips_cdmm_device *cdev = to_mips_cdmm_device(dev);
    505
    506	kfree(cdev);
    507}
    508
    509/**
    510 * mips_cdmm_bus_discover() - Discover the devices on the CDMM bus.
    511 * @bus:	CDMM bus information, must already be set up.
    512 */
    513static void mips_cdmm_bus_discover(struct mips_cdmm_bus *bus)
    514{
    515	void __iomem *cdmm;
    516	u32 acsr;
    517	unsigned int drb, type, size, rev;
    518	struct mips_cdmm_device *dev;
    519	unsigned int cpu = smp_processor_id();
    520	int ret = 0;
    521	int id = 0;
    522
    523	/* Skip the first block if it's reserved for more registers */
    524	drb = bus->drbs_reserved;
    525	cdmm = bus->regs;
    526
    527	/* Discover devices */
    528	bus->discovered = true;
    529	pr_info("cdmm%u discovery (%u blocks)\n", cpu, bus->drbs);
    530	for (; drb < bus->drbs; drb += size + 1) {
    531		acsr = __raw_readl(cdmm + drb * CDMM_DRB_SIZE);
    532		type = (acsr & CDMM_ACSR_DEVTYPE) >> CDMM_ACSR_DEVTYPE_SHIFT;
    533		size = (acsr & CDMM_ACSR_DEVSIZE) >> CDMM_ACSR_DEVSIZE_SHIFT;
    534		rev  = (acsr & CDMM_ACSR_DEVREV)  >> CDMM_ACSR_DEVREV_SHIFT;
    535
    536		if (!type)
    537			continue;
    538
    539		pr_info("cdmm%u-%u: @%u (%#x..%#x), type 0x%02x, rev %u\n",
    540			cpu, id, drb, drb * CDMM_DRB_SIZE,
    541			(drb + size + 1) * CDMM_DRB_SIZE - 1,
    542			type, rev);
    543
    544		dev = kzalloc(sizeof(*dev), GFP_KERNEL);
    545		if (!dev)
    546			break;
    547
    548		dev->cpu = cpu;
    549		dev->res.start = bus->phys + drb * CDMM_DRB_SIZE;
    550		dev->res.end = bus->phys +
    551				(drb + size + 1) * CDMM_DRB_SIZE - 1;
    552		dev->res.flags = IORESOURCE_MEM;
    553		dev->type = type;
    554		dev->rev = rev;
    555		dev->dev.parent = get_cpu_device(cpu);
    556		dev->dev.bus = &mips_cdmm_bustype;
    557		dev->dev.id = atomic_inc_return(&mips_cdmm_next_id);
    558		dev->dev.release = mips_cdmm_release;
    559
    560		dev_set_name(&dev->dev, "cdmm%u-%u", cpu, id);
    561		++id;
    562		ret = device_register(&dev->dev);
    563		if (ret)
    564			put_device(&dev->dev);
    565	}
    566}
    567
    568
    569/*
    570 * CPU hotplug and initialisation
    571 *
    572 * All the CDMM driver callbacks need to be executed on the appropriate CPU from
    573 * workqueues. For the CPU callbacks, they need to be called for all devices on
    574 * that CPU, so the work function calls bus_for_each_dev, using a helper
    575 * (generated with BUILD_PERDEV_HELPER) to call the driver callback if the
    576 * device's CPU matches.
    577 */
    578
    579/**
    580 * BUILD_PERDEV_HELPER() - Helper to call a CDMM driver callback if CPU matches.
    581 * @_name:	Name of CDMM driver callback function.
    582 *
    583 * Generates a bus_for_each_dev callback function to call a specific CDMM driver
    584 * callback function for the device if the device's CPU matches that pointed to
    585 * by the data argument.
    586 *
    587 * This is used for informing drivers for all devices on a given CPU of some
    588 * event (such as the CPU going online/offline).
    589 *
    590 * It is expected to already be called from the appropriate CPU.
    591 */
    592#define BUILD_PERDEV_HELPER(_name)					\
    593static int mips_cdmm_##_name##_helper(struct device *dev, void *data)	\
    594{									\
    595	struct mips_cdmm_device *cdev = to_mips_cdmm_device(dev);	\
    596	struct mips_cdmm_driver *cdrv;					\
    597	unsigned int cpu = *(unsigned int *)data;			\
    598									\
    599	if (cdev->cpu != cpu || !dev->driver)				\
    600		return 0;						\
    601									\
    602	cdrv = to_mips_cdmm_driver(dev->driver);			\
    603	if (!cdrv->_name)						\
    604		return 0;						\
    605	return cdrv->_name(cdev);					\
    606}
    607
    608/* bus_for_each_dev callback helper functions */
    609BUILD_PERDEV_HELPER(cpu_down)       /* int mips_cdmm_cpu_down_helper(...) */
    610BUILD_PERDEV_HELPER(cpu_up)         /* int mips_cdmm_cpu_up_helper(...) */
    611
    612/**
    613 * mips_cdmm_cpu_down_prep() - Callback for CPUHP DOWN_PREP:
    614 *			       Tear down the CDMM bus.
    615 * @cpu:	unsigned int CPU number.
    616 *
    617 * This function is executed on the hotplugged CPU and calls the CDMM
    618 * driver cpu_down callback for all devices on that CPU.
    619 */
    620static int mips_cdmm_cpu_down_prep(unsigned int cpu)
    621{
    622	struct mips_cdmm_bus *bus;
    623	long ret;
    624
    625	/* Inform all the devices on the bus */
    626	ret = bus_for_each_dev(&mips_cdmm_bustype, NULL, &cpu,
    627			       mips_cdmm_cpu_down_helper);
    628
    629	/*
    630	 * While bus is offline, each use of it should reconfigure it just in
    631	 * case it is first use when coming back online again.
    632	 */
    633	bus = mips_cdmm_get_bus();
    634	if (!IS_ERR(bus))
    635		bus->offline = true;
    636
    637	return ret;
    638}
    639
    640/**
    641 * mips_cdmm_cpu_online() - Callback for CPUHP ONLINE: Bring up the CDMM bus.
    642 * @cpu:	unsigned int CPU number.
    643 *
    644 * This work_on_cpu callback function is executed on a given CPU to discover
    645 * CDMM devices on that CPU, or to call the CDMM driver cpu_up callback for all
    646 * devices already discovered on that CPU.
    647 *
    648 * It is used as work_on_cpu callback function during
    649 * initialisation. When CPUs are brought online the function is
    650 * invoked directly on the hotplugged CPU.
    651 */
    652static int mips_cdmm_cpu_online(unsigned int cpu)
    653{
    654	struct mips_cdmm_bus *bus;
    655	long ret;
    656
    657	bus = mips_cdmm_get_bus();
    658	ret = mips_cdmm_setup(bus);
    659	if (ret)
    660		return ret;
    661
    662	/* Bus now set up, so we can drop the offline flag if still set */
    663	bus->offline = false;
    664
    665	if (!bus->discovered)
    666		mips_cdmm_bus_discover(bus);
    667	else
    668		/* Inform all the devices on the bus */
    669		ret = bus_for_each_dev(&mips_cdmm_bustype, NULL, &cpu,
    670				       mips_cdmm_cpu_up_helper);
    671
    672	return ret;
    673}
    674
    675/**
    676 * mips_cdmm_init() - Initialise CDMM bus.
    677 *
    678 * Initialise CDMM bus, discover CDMM devices for online CPUs, and arrange for
    679 * hotplug notifications so the CDMM drivers can be kept up to date.
    680 */
    681static int __init mips_cdmm_init(void)
    682{
    683	int ret;
    684
    685	/* Register the bus */
    686	ret = bus_register(&mips_cdmm_bustype);
    687	if (ret)
    688		return ret;
    689
    690	/* We want to be notified about new CPUs */
    691	ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "bus/cdmm:online",
    692				mips_cdmm_cpu_online, mips_cdmm_cpu_down_prep);
    693	if (ret < 0)
    694		pr_warn("cdmm: Failed to register CPU notifier\n");
    695
    696	return ret;
    697}
    698subsys_initcall(mips_cdmm_init);