linux-stable/drivers/mcb/mcb-core.c

519 lines
11 KiB
C
Raw Permalink Normal View History

// SPDX-License-Identifier: GPL-2.0-only
/*
* MEN Chameleon Bus.
*
* Copyright (C) 2013 MEN Mikroelektronik GmbH (www.men.de)
* Author: Johannes Thumshirn <johannes.thumshirn@men.de>
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/idr.h>
#include <linux/mcb.h>
static DEFINE_IDA(mcb_ida);
static const struct mcb_device_id *mcb_match_id(const struct mcb_device_id *ids,
struct mcb_device *dev)
{
if (ids) {
while (ids->device) {
if (ids->device == dev->id)
return ids;
ids++;
}
}
return NULL;
}
static int mcb_match(struct device *dev, const struct device_driver *drv)
{
const struct mcb_driver *mdrv = to_mcb_driver(drv);
struct mcb_device *mdev = to_mcb_device(dev);
const struct mcb_device_id *found_id;
found_id = mcb_match_id(mdrv->id_table, mdev);
if (found_id)
return 1;
return 0;
}
static int mcb_uevent(const struct device *dev, struct kobj_uevent_env *env)
{
const struct mcb_device *mdev = to_mcb_device(dev);
int ret;
ret = add_uevent_var(env, "MODALIAS=mcb:16z%03d", mdev->id);
if (ret)
return -ENOMEM;
return 0;
}
static int mcb_probe(struct device *dev)
{
struct mcb_driver *mdrv = to_mcb_driver(dev->driver);
struct mcb_device *mdev = to_mcb_device(dev);
const struct mcb_device_id *found_id;
struct module *carrier_mod;
int ret;
found_id = mcb_match_id(mdrv->id_table, mdev);
if (!found_id)
return -ENODEV;
carrier_mod = mdev->dev.parent->driver->owner;
if (!try_module_get(carrier_mod))
return -EINVAL;
get_device(dev);
ret = mdrv->probe(mdev, found_id);
if (ret) {
module_put(carrier_mod);
put_device(dev);
}
return ret;
}
bus: Make remove callback return void The driver core ignores the return value of this callback because there is only little it can do when a device disappears. This is the final bit of a long lasting cleanup quest where several buses were converted to also return void from their remove callback. Additionally some resource leaks were fixed that were caused by drivers returning an error code in the expectation that the driver won't go away. With struct bus_type::remove returning void it's prevented that newly implemented buses return an ignored error code and so don't anticipate wrong expectations for driver authors. Reviewed-by: Tom Rix <trix@redhat.com> (For fpga) Reviewed-by: Mathieu Poirier <mathieu.poirier@linaro.org> Reviewed-by: Cornelia Huck <cohuck@redhat.com> (For drivers/s390 and drivers/vfio) Acked-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk> (For ARM, Amba and related parts) Acked-by: Mark Brown <broonie@kernel.org> Acked-by: Chen-Yu Tsai <wens@csie.org> (for sunxi-rsb) Acked-by: Pali Rohár <pali@kernel.org> Acked-by: Mauro Carvalho Chehab <mchehab@kernel.org> (for media) Acked-by: Hans de Goede <hdegoede@redhat.com> (For drivers/platform) Acked-by: Alexandre Belloni <alexandre.belloni@bootlin.com> Acked-By: Vinod Koul <vkoul@kernel.org> Acked-by: Juergen Gross <jgross@suse.com> (For xen) Acked-by: Lee Jones <lee.jones@linaro.org> (For mfd) Acked-by: Johannes Thumshirn <jth@kernel.org> (For mcb) Acked-by: Johan Hovold <johan@kernel.org> Acked-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org> (For slimbus) Acked-by: Kirti Wankhede <kwankhede@nvidia.com> (For vfio) Acked-by: Maximilian Luz <luzmaximilian@gmail.com> Acked-by: Heikki Krogerus <heikki.krogerus@linux.intel.com> (For ulpi and typec) Acked-by: Samuel Iglesias Gonsálvez <siglesias@igalia.com> (For ipack) Acked-by: Geoff Levand <geoff@infradead.org> (For ps3) Acked-by: Yehezkel Bernat <YehezkelShB@gmail.com> (For thunderbolt) Acked-by: Alexander Shishkin <alexander.shishkin@linux.intel.com> (For intel_th) Acked-by: Dominik Brodowski <linux@dominikbrodowski.net> (For pcmcia) Acked-by: Rafael J. Wysocki <rafael@kernel.org> (For ACPI) Acked-by: Bjorn Andersson <bjorn.andersson@linaro.org> (rpmsg and apr) Acked-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> (For intel-ish-hid) Acked-by: Dan Williams <dan.j.williams@intel.com> (For CXL, DAX, and NVDIMM) Acked-by: William Breathitt Gray <vilhelm.gray@gmail.com> (For isa) Acked-by: Stefan Richter <stefanr@s5r6.in-berlin.de> (For firewire) Acked-by: Benjamin Tissoires <benjamin.tissoires@redhat.com> (For hid) Acked-by: Thorsten Scherer <t.scherer@eckelmann.de> (For siox) Acked-by: Sven Van Asbroeck <TheSven73@gmail.com> (For anybuss) Acked-by: Ulf Hansson <ulf.hansson@linaro.org> (For MMC) Acked-by: Wolfram Sang <wsa@kernel.org> # for I2C Acked-by: Sudeep Holla <sudeep.holla@arm.com> Acked-by: Geert Uytterhoeven <geert@linux-m68k.org> Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com> Acked-by: Finn Thain <fthain@linux-m68k.org> Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> Link: https://lore.kernel.org/r/20210713193522.1770306-6-u.kleine-koenig@pengutronix.de Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2021-07-13 19:35:22 +00:00
static void mcb_remove(struct device *dev)
{
struct mcb_driver *mdrv = to_mcb_driver(dev->driver);
struct mcb_device *mdev = to_mcb_device(dev);
struct module *carrier_mod;
mdrv->remove(mdev);
carrier_mod = mdev->dev.parent->driver->owner;
module_put(carrier_mod);
put_device(&mdev->dev);
}
static void mcb_shutdown(struct device *dev)
{
mcb: Implement bus->dev.release callback The mcb_bus structure previously was released in mcb_release_bus. This lead to the following warning on module unload: ------------[ cut here ]------------ WARNING: CPU: 1 PID: 2032 at drivers/base/core.c:251 device_release+0x73/0x90 Device 'mcb:0' does not have a release() function, it is broken and must be fixed. Modules linked in: men_z135_uart mcb_pci(-) mcb CPU: 1 PID: 2032 Comm: rmmod Not tainted 4.6.0-rc4+ #3 Hardware name: N/A N/A/COMe-mBTi10, BIOS MVV1R921 X64 10/14/2015 00000286 00000286 c0117de4 c12d6f16 c0117e2c c18be0d3 c0117dfc c104f6e1 000000fb f5ccbe08 f5ccbe00 f5c64600 c0117e18 c104f728 00000009 00000000 c0117e10 c18db674 c0117e2c c0117e3c c13ce5c3 c18be0d3 000000fb c18db674 Call Trace: [<c12d6f16>] dump_stack+0x47/0x61 [<c104f6e1>] __warn+0xc1/0xe0 [<c104f728>] warn_slowpath_fmt+0x28/0x30 [<c13ce5c3>] device_release+0x73/0x90 [<c12d92e4>] kobject_release+0x34/0x80 [<c12d929d>] ? kobject_del+0x2d/0x40 [<c12d9205>] kobject_put+0x25/0x50 [<c13ce77f>] put_device+0xf/0x20 [<c13d114b>] klist_devices_put+0xb/0x10 [<c1752673>] klist_next+0x73/0xf0 [<c13d1140>] ? unbind_store+0x100/0x100 [<f8a23370>] ? mcb_bus_add_devices+0x30/0x30 [mcb] [<c13d0a81>] bus_for_each_dev+0x51/0x80 [<f8a23319>] mcb_release_bus+0x19/0x40 [mcb] [<f8a23370>] ? mcb_bus_add_devices+0x30/0x30 [mcb] [<f8a2b033>] mcb_pci_remove+0x13/0x20 [mcb_pci] [<c130d358>] pci_device_remove+0x28/0xb0 [<c13d201b>] __device_release_driver+0x7b/0x110 [<c13d2847>] driver_detach+0x87/0x90 [<c13d1b9b>] bus_remove_driver+0x3b/0x80 [<c13d2ed0>] driver_unregister+0x20/0x50 [<c130be53>] pci_unregister_driver+0x13/0x60 [<f8a2b1f4>] mcb_pci_driver_exit+0xd/0xf [mcb_pci] [<c10be588>] SyS_delete_module+0x138/0x200 [<c1159208>] ? ____fput+0x8/0x10 [<c1068054>] ? task_work_run+0x74/0x90 [<c1001879>] do_fast_syscall_32+0x69/0x120 [<c1757597>] sysenter_past_esp+0x40/0x6a ---[ end trace 1ed34c2aa3019875 ]--- Release a mcb_bus' memory on the device's release callback, to avoid above warning. Signed-off-by: Johannes Thumshirn <jthumshirn@suse.de> Reported-by: Andreas Werner <andreas.werner@men.de> Tested-by: Andreas Werner <andreas.werner@men.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2016-05-03 10:42:03 +00:00
struct mcb_driver *mdrv = to_mcb_driver(dev->driver);
struct mcb_device *mdev = to_mcb_device(dev);
if (mdrv && mdrv->shutdown)
mdrv->shutdown(mdev);
}
static ssize_t revision_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct mcb_bus *bus = to_mcb_bus(dev);
return scnprintf(buf, PAGE_SIZE, "%d\n", bus->revision);
}
static DEVICE_ATTR_RO(revision);
static ssize_t model_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct mcb_bus *bus = to_mcb_bus(dev);
return scnprintf(buf, PAGE_SIZE, "%c\n", bus->model);
}
static DEVICE_ATTR_RO(model);
static ssize_t minor_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct mcb_bus *bus = to_mcb_bus(dev);
return scnprintf(buf, PAGE_SIZE, "%d\n", bus->minor);
}
static DEVICE_ATTR_RO(minor);
static ssize_t name_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct mcb_bus *bus = to_mcb_bus(dev);
return scnprintf(buf, PAGE_SIZE, "%s\n", bus->name);
}
static DEVICE_ATTR_RO(name);
static struct attribute *mcb_bus_attrs[] = {
&dev_attr_revision.attr,
&dev_attr_model.attr,
&dev_attr_minor.attr,
&dev_attr_name.attr,
NULL,
};
static const struct attribute_group mcb_carrier_group = {
.attrs = mcb_bus_attrs,
};
static const struct attribute_group *mcb_carrier_groups[] = {
&mcb_carrier_group,
NULL,
};
static const struct bus_type mcb_bus_type = {
.name = "mcb",
.match = mcb_match,
.uevent = mcb_uevent,
.probe = mcb_probe,
.remove = mcb_remove,
.shutdown = mcb_shutdown,
};
static const struct device_type mcb_carrier_device_type = {
.name = "mcb-carrier",
.groups = mcb_carrier_groups,
};
/**
* __mcb_register_driver() - Register a @mcb_driver at the system
* @drv: The @mcb_driver
* @owner: The @mcb_driver's module
* @mod_name: The name of the @mcb_driver's module
*
* Register a @mcb_driver at the system. Perform some sanity checks, if
* the .probe and .remove methods are provided by the driver.
*/
int __mcb_register_driver(struct mcb_driver *drv, struct module *owner,
const char *mod_name)
{
if (!drv->probe || !drv->remove)
return -EINVAL;
drv->driver.owner = owner;
drv->driver.bus = &mcb_bus_type;
drv->driver.mod_name = mod_name;
return driver_register(&drv->driver);
}
EXPORT_SYMBOL_NS_GPL(__mcb_register_driver, "MCB");
/**
* mcb_unregister_driver() - Unregister a @mcb_driver from the system
* @drv: The @mcb_driver
*
* Unregister a @mcb_driver from the system.
*/
void mcb_unregister_driver(struct mcb_driver *drv)
{
driver_unregister(&drv->driver);
}
EXPORT_SYMBOL_NS_GPL(mcb_unregister_driver, "MCB");
static void mcb_release_dev(struct device *dev)
{
struct mcb_device *mdev = to_mcb_device(dev);
mcb_bus_put(mdev->bus);
kfree(mdev);
}
/**
* mcb_device_register() - Register a mcb_device
* @bus: The @mcb_bus of the device
* @dev: The @mcb_device
*
* Register a specific @mcb_device at a @mcb_bus and the system itself.
*/
int mcb_device_register(struct mcb_bus *bus, struct mcb_device *dev)
{
int ret;
int device_id;
device_initialize(&dev->dev);
mcb: Implement bus->dev.release callback The mcb_bus structure previously was released in mcb_release_bus. This lead to the following warning on module unload: ------------[ cut here ]------------ WARNING: CPU: 1 PID: 2032 at drivers/base/core.c:251 device_release+0x73/0x90 Device 'mcb:0' does not have a release() function, it is broken and must be fixed. Modules linked in: men_z135_uart mcb_pci(-) mcb CPU: 1 PID: 2032 Comm: rmmod Not tainted 4.6.0-rc4+ #3 Hardware name: N/A N/A/COMe-mBTi10, BIOS MVV1R921 X64 10/14/2015 00000286 00000286 c0117de4 c12d6f16 c0117e2c c18be0d3 c0117dfc c104f6e1 000000fb f5ccbe08 f5ccbe00 f5c64600 c0117e18 c104f728 00000009 00000000 c0117e10 c18db674 c0117e2c c0117e3c c13ce5c3 c18be0d3 000000fb c18db674 Call Trace: [<c12d6f16>] dump_stack+0x47/0x61 [<c104f6e1>] __warn+0xc1/0xe0 [<c104f728>] warn_slowpath_fmt+0x28/0x30 [<c13ce5c3>] device_release+0x73/0x90 [<c12d92e4>] kobject_release+0x34/0x80 [<c12d929d>] ? kobject_del+0x2d/0x40 [<c12d9205>] kobject_put+0x25/0x50 [<c13ce77f>] put_device+0xf/0x20 [<c13d114b>] klist_devices_put+0xb/0x10 [<c1752673>] klist_next+0x73/0xf0 [<c13d1140>] ? unbind_store+0x100/0x100 [<f8a23370>] ? mcb_bus_add_devices+0x30/0x30 [mcb] [<c13d0a81>] bus_for_each_dev+0x51/0x80 [<f8a23319>] mcb_release_bus+0x19/0x40 [mcb] [<f8a23370>] ? mcb_bus_add_devices+0x30/0x30 [mcb] [<f8a2b033>] mcb_pci_remove+0x13/0x20 [mcb_pci] [<c130d358>] pci_device_remove+0x28/0xb0 [<c13d201b>] __device_release_driver+0x7b/0x110 [<c13d2847>] driver_detach+0x87/0x90 [<c13d1b9b>] bus_remove_driver+0x3b/0x80 [<c13d2ed0>] driver_unregister+0x20/0x50 [<c130be53>] pci_unregister_driver+0x13/0x60 [<f8a2b1f4>] mcb_pci_driver_exit+0xd/0xf [mcb_pci] [<c10be588>] SyS_delete_module+0x138/0x200 [<c1159208>] ? ____fput+0x8/0x10 [<c1068054>] ? task_work_run+0x74/0x90 [<c1001879>] do_fast_syscall_32+0x69/0x120 [<c1757597>] sysenter_past_esp+0x40/0x6a ---[ end trace 1ed34c2aa3019875 ]--- Release a mcb_bus' memory on the device's release callback, to avoid above warning. Signed-off-by: Johannes Thumshirn <jthumshirn@suse.de> Reported-by: Andreas Werner <andreas.werner@men.de> Tested-by: Andreas Werner <andreas.werner@men.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2016-05-03 10:42:03 +00:00
mcb_bus_get(bus);
dev->dev.bus = &mcb_bus_type;
dev->dev.parent = bus->dev.parent;
dev->dev.release = mcb_release_dev;
dev->dma_dev = bus->carrier;
device_id = dev->id;
dev_set_name(&dev->dev, "mcb%d-16z%03d-%d:%d:%d",
bus->bus_nr, device_id, dev->inst, dev->group, dev->var);
ret = device_add(&dev->dev);
if (ret < 0) {
pr_err("Failed registering device 16z%03d on bus mcb%d (%d)\n",
device_id, bus->bus_nr, ret);
goto out;
}
return 0;
out:
put_device(&dev->dev);
return ret;
}
EXPORT_SYMBOL_NS_GPL(mcb_device_register, "MCB");
mcb: Implement bus->dev.release callback The mcb_bus structure previously was released in mcb_release_bus. This lead to the following warning on module unload: ------------[ cut here ]------------ WARNING: CPU: 1 PID: 2032 at drivers/base/core.c:251 device_release+0x73/0x90 Device 'mcb:0' does not have a release() function, it is broken and must be fixed. Modules linked in: men_z135_uart mcb_pci(-) mcb CPU: 1 PID: 2032 Comm: rmmod Not tainted 4.6.0-rc4+ #3 Hardware name: N/A N/A/COMe-mBTi10, BIOS MVV1R921 X64 10/14/2015 00000286 00000286 c0117de4 c12d6f16 c0117e2c c18be0d3 c0117dfc c104f6e1 000000fb f5ccbe08 f5ccbe00 f5c64600 c0117e18 c104f728 00000009 00000000 c0117e10 c18db674 c0117e2c c0117e3c c13ce5c3 c18be0d3 000000fb c18db674 Call Trace: [<c12d6f16>] dump_stack+0x47/0x61 [<c104f6e1>] __warn+0xc1/0xe0 [<c104f728>] warn_slowpath_fmt+0x28/0x30 [<c13ce5c3>] device_release+0x73/0x90 [<c12d92e4>] kobject_release+0x34/0x80 [<c12d929d>] ? kobject_del+0x2d/0x40 [<c12d9205>] kobject_put+0x25/0x50 [<c13ce77f>] put_device+0xf/0x20 [<c13d114b>] klist_devices_put+0xb/0x10 [<c1752673>] klist_next+0x73/0xf0 [<c13d1140>] ? unbind_store+0x100/0x100 [<f8a23370>] ? mcb_bus_add_devices+0x30/0x30 [mcb] [<c13d0a81>] bus_for_each_dev+0x51/0x80 [<f8a23319>] mcb_release_bus+0x19/0x40 [mcb] [<f8a23370>] ? mcb_bus_add_devices+0x30/0x30 [mcb] [<f8a2b033>] mcb_pci_remove+0x13/0x20 [mcb_pci] [<c130d358>] pci_device_remove+0x28/0xb0 [<c13d201b>] __device_release_driver+0x7b/0x110 [<c13d2847>] driver_detach+0x87/0x90 [<c13d1b9b>] bus_remove_driver+0x3b/0x80 [<c13d2ed0>] driver_unregister+0x20/0x50 [<c130be53>] pci_unregister_driver+0x13/0x60 [<f8a2b1f4>] mcb_pci_driver_exit+0xd/0xf [mcb_pci] [<c10be588>] SyS_delete_module+0x138/0x200 [<c1159208>] ? ____fput+0x8/0x10 [<c1068054>] ? task_work_run+0x74/0x90 [<c1001879>] do_fast_syscall_32+0x69/0x120 [<c1757597>] sysenter_past_esp+0x40/0x6a ---[ end trace 1ed34c2aa3019875 ]--- Release a mcb_bus' memory on the device's release callback, to avoid above warning. Signed-off-by: Johannes Thumshirn <jthumshirn@suse.de> Reported-by: Andreas Werner <andreas.werner@men.de> Tested-by: Andreas Werner <andreas.werner@men.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2016-05-03 10:42:03 +00:00
static void mcb_free_bus(struct device *dev)
{
struct mcb_bus *bus = to_mcb_bus(dev);
put_device(bus->carrier);
ida_free(&mcb_ida, bus->bus_nr);
mcb: Implement bus->dev.release callback The mcb_bus structure previously was released in mcb_release_bus. This lead to the following warning on module unload: ------------[ cut here ]------------ WARNING: CPU: 1 PID: 2032 at drivers/base/core.c:251 device_release+0x73/0x90 Device 'mcb:0' does not have a release() function, it is broken and must be fixed. Modules linked in: men_z135_uart mcb_pci(-) mcb CPU: 1 PID: 2032 Comm: rmmod Not tainted 4.6.0-rc4+ #3 Hardware name: N/A N/A/COMe-mBTi10, BIOS MVV1R921 X64 10/14/2015 00000286 00000286 c0117de4 c12d6f16 c0117e2c c18be0d3 c0117dfc c104f6e1 000000fb f5ccbe08 f5ccbe00 f5c64600 c0117e18 c104f728 00000009 00000000 c0117e10 c18db674 c0117e2c c0117e3c c13ce5c3 c18be0d3 000000fb c18db674 Call Trace: [<c12d6f16>] dump_stack+0x47/0x61 [<c104f6e1>] __warn+0xc1/0xe0 [<c104f728>] warn_slowpath_fmt+0x28/0x30 [<c13ce5c3>] device_release+0x73/0x90 [<c12d92e4>] kobject_release+0x34/0x80 [<c12d929d>] ? kobject_del+0x2d/0x40 [<c12d9205>] kobject_put+0x25/0x50 [<c13ce77f>] put_device+0xf/0x20 [<c13d114b>] klist_devices_put+0xb/0x10 [<c1752673>] klist_next+0x73/0xf0 [<c13d1140>] ? unbind_store+0x100/0x100 [<f8a23370>] ? mcb_bus_add_devices+0x30/0x30 [mcb] [<c13d0a81>] bus_for_each_dev+0x51/0x80 [<f8a23319>] mcb_release_bus+0x19/0x40 [mcb] [<f8a23370>] ? mcb_bus_add_devices+0x30/0x30 [mcb] [<f8a2b033>] mcb_pci_remove+0x13/0x20 [mcb_pci] [<c130d358>] pci_device_remove+0x28/0xb0 [<c13d201b>] __device_release_driver+0x7b/0x110 [<c13d2847>] driver_detach+0x87/0x90 [<c13d1b9b>] bus_remove_driver+0x3b/0x80 [<c13d2ed0>] driver_unregister+0x20/0x50 [<c130be53>] pci_unregister_driver+0x13/0x60 [<f8a2b1f4>] mcb_pci_driver_exit+0xd/0xf [mcb_pci] [<c10be588>] SyS_delete_module+0x138/0x200 [<c1159208>] ? ____fput+0x8/0x10 [<c1068054>] ? task_work_run+0x74/0x90 [<c1001879>] do_fast_syscall_32+0x69/0x120 [<c1757597>] sysenter_past_esp+0x40/0x6a ---[ end trace 1ed34c2aa3019875 ]--- Release a mcb_bus' memory on the device's release callback, to avoid above warning. Signed-off-by: Johannes Thumshirn <jthumshirn@suse.de> Reported-by: Andreas Werner <andreas.werner@men.de> Tested-by: Andreas Werner <andreas.werner@men.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2016-05-03 10:42:03 +00:00
kfree(bus);
}
/**
* mcb_alloc_bus() - Allocate a new @mcb_bus
* @carrier: generic &struct device for the carrier device
*
* Allocate a new @mcb_bus.
*/
struct mcb_bus *mcb_alloc_bus(struct device *carrier)
{
struct mcb_bus *bus;
int bus_nr;
int rc;
bus = kzalloc(sizeof(struct mcb_bus), GFP_KERNEL);
if (!bus)
return ERR_PTR(-ENOMEM);
bus_nr = ida_alloc(&mcb_ida, GFP_KERNEL);
if (bus_nr < 0) {
kfree(bus);
return ERR_PTR(bus_nr);
}
bus->bus_nr = bus_nr;
mcb: Implement bus->dev.release callback The mcb_bus structure previously was released in mcb_release_bus. This lead to the following warning on module unload: ------------[ cut here ]------------ WARNING: CPU: 1 PID: 2032 at drivers/base/core.c:251 device_release+0x73/0x90 Device 'mcb:0' does not have a release() function, it is broken and must be fixed. Modules linked in: men_z135_uart mcb_pci(-) mcb CPU: 1 PID: 2032 Comm: rmmod Not tainted 4.6.0-rc4+ #3 Hardware name: N/A N/A/COMe-mBTi10, BIOS MVV1R921 X64 10/14/2015 00000286 00000286 c0117de4 c12d6f16 c0117e2c c18be0d3 c0117dfc c104f6e1 000000fb f5ccbe08 f5ccbe00 f5c64600 c0117e18 c104f728 00000009 00000000 c0117e10 c18db674 c0117e2c c0117e3c c13ce5c3 c18be0d3 000000fb c18db674 Call Trace: [<c12d6f16>] dump_stack+0x47/0x61 [<c104f6e1>] __warn+0xc1/0xe0 [<c104f728>] warn_slowpath_fmt+0x28/0x30 [<c13ce5c3>] device_release+0x73/0x90 [<c12d92e4>] kobject_release+0x34/0x80 [<c12d929d>] ? kobject_del+0x2d/0x40 [<c12d9205>] kobject_put+0x25/0x50 [<c13ce77f>] put_device+0xf/0x20 [<c13d114b>] klist_devices_put+0xb/0x10 [<c1752673>] klist_next+0x73/0xf0 [<c13d1140>] ? unbind_store+0x100/0x100 [<f8a23370>] ? mcb_bus_add_devices+0x30/0x30 [mcb] [<c13d0a81>] bus_for_each_dev+0x51/0x80 [<f8a23319>] mcb_release_bus+0x19/0x40 [mcb] [<f8a23370>] ? mcb_bus_add_devices+0x30/0x30 [mcb] [<f8a2b033>] mcb_pci_remove+0x13/0x20 [mcb_pci] [<c130d358>] pci_device_remove+0x28/0xb0 [<c13d201b>] __device_release_driver+0x7b/0x110 [<c13d2847>] driver_detach+0x87/0x90 [<c13d1b9b>] bus_remove_driver+0x3b/0x80 [<c13d2ed0>] driver_unregister+0x20/0x50 [<c130be53>] pci_unregister_driver+0x13/0x60 [<f8a2b1f4>] mcb_pci_driver_exit+0xd/0xf [mcb_pci] [<c10be588>] SyS_delete_module+0x138/0x200 [<c1159208>] ? ____fput+0x8/0x10 [<c1068054>] ? task_work_run+0x74/0x90 [<c1001879>] do_fast_syscall_32+0x69/0x120 [<c1757597>] sysenter_past_esp+0x40/0x6a ---[ end trace 1ed34c2aa3019875 ]--- Release a mcb_bus' memory on the device's release callback, to avoid above warning. Signed-off-by: Johannes Thumshirn <jthumshirn@suse.de> Reported-by: Andreas Werner <andreas.werner@men.de> Tested-by: Andreas Werner <andreas.werner@men.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2016-05-03 10:42:03 +00:00
bus->carrier = get_device(carrier);
device_initialize(&bus->dev);
bus->dev.parent = carrier;
bus->dev.bus = &mcb_bus_type;
bus->dev.type = &mcb_carrier_device_type;
bus->dev.release = mcb_free_bus;
dev_set_name(&bus->dev, "mcb:%d", bus_nr);
rc = device_add(&bus->dev);
if (rc)
goto err_put;
return bus;
err_put:
put_device(&bus->dev);
return ERR_PTR(rc);
}
EXPORT_SYMBOL_NS_GPL(mcb_alloc_bus, "MCB");
static int __mcb_devices_unregister(struct device *dev, void *data)
{
device_unregister(dev);
return 0;
}
static void mcb_devices_unregister(struct mcb_bus *bus)
{
bus_for_each_dev(bus->dev.bus, NULL, NULL, __mcb_devices_unregister);
}
/**
* mcb_release_bus() - Free a @mcb_bus
* @bus: The @mcb_bus to release
*
* Release an allocated @mcb_bus from the system.
*/
void mcb_release_bus(struct mcb_bus *bus)
{
mcb_devices_unregister(bus);
}
EXPORT_SYMBOL_NS_GPL(mcb_release_bus, "MCB");
/**
* mcb_bus_get() - Increment refcnt
* @bus: The @mcb_bus
*
* Get a @mcb_bus' ref
*/
struct mcb_bus *mcb_bus_get(struct mcb_bus *bus)
{
if (bus)
get_device(&bus->dev);
return bus;
}
EXPORT_SYMBOL_NS_GPL(mcb_bus_get, "MCB");
/**
* mcb_bus_put() - Decrement refcnt
* @bus: The @mcb_bus
*
* Release a @mcb_bus' ref
*/
void mcb_bus_put(struct mcb_bus *bus)
{
if (bus)
put_device(&bus->dev);
}
EXPORT_SYMBOL_NS_GPL(mcb_bus_put, "MCB");
/**
* mcb_alloc_dev() - Allocate a device
* @bus: The @mcb_bus the device is part of
*
* Allocate a @mcb_device and add bus.
*/
struct mcb_device *mcb_alloc_dev(struct mcb_bus *bus)
{
struct mcb_device *dev;
dev = kzalloc(sizeof(struct mcb_device), GFP_KERNEL);
if (!dev)
return NULL;
dev->bus = bus;
return dev;
}
EXPORT_SYMBOL_NS_GPL(mcb_alloc_dev, "MCB");
/**
* mcb_free_dev() - Free @mcb_device
* @dev: The device to free
*
* Free a @mcb_device
*/
void mcb_free_dev(struct mcb_device *dev)
{
kfree(dev);
}
EXPORT_SYMBOL_NS_GPL(mcb_free_dev, "MCB");
static int __mcb_bus_add_devices(struct device *dev, void *data)
{
int retval;
retval = device_attach(dev);
if (retval < 0) {
dev_err(dev, "Error adding device (%d)\n", retval);
return retval;
}
return 0;
}
/**
* mcb_bus_add_devices() - Add devices in the bus' internal device list
* @bus: The @mcb_bus we add the devices
*
* Add devices in the bus' internal device list to the system.
*/
void mcb_bus_add_devices(const struct mcb_bus *bus)
{
bus_for_each_dev(bus->dev.bus, NULL, NULL, __mcb_bus_add_devices);
}
EXPORT_SYMBOL_NS_GPL(mcb_bus_add_devices, "MCB");
/**
* mcb_get_resource() - get a resource for a mcb device
* @dev: the mcb device
* @type: the type of resource
*/
struct resource *mcb_get_resource(struct mcb_device *dev, unsigned int type)
{
if (type == IORESOURCE_MEM)
return &dev->mem;
else if (type == IORESOURCE_IRQ)
return &dev->irq;
else
return NULL;
}
EXPORT_SYMBOL_NS_GPL(mcb_get_resource, "MCB");
/**
* mcb_request_mem() - Request memory
* @dev: The @mcb_device the memory is for
* @name: The name for the memory reference.
*
* Request memory for a @mcb_device. If @name is NULL the driver name will
* be used.
*/
struct resource *mcb_request_mem(struct mcb_device *dev, const char *name)
{
struct resource *mem;
u32 size;
if (!name)
name = dev->dev.driver->name;
size = resource_size(&dev->mem);
mem = request_mem_region(dev->mem.start, size, name);
if (!mem)
return ERR_PTR(-EBUSY);
return mem;
}
EXPORT_SYMBOL_NS_GPL(mcb_request_mem, "MCB");
/**
* mcb_release_mem() - Release memory requested by device
* @mem: The memory resource to be released
*
* Release memory that was prior requested via @mcb_request_mem().
*/
void mcb_release_mem(struct resource *mem)
{
u32 size;
size = resource_size(mem);
release_mem_region(mem->start, size);
}
EXPORT_SYMBOL_NS_GPL(mcb_release_mem, "MCB");
static int __mcb_get_irq(struct mcb_device *dev)
{
struct resource *irq;
irq = mcb_get_resource(dev, IORESOURCE_IRQ);
return irq->start;
}
/**
* mcb_get_irq() - Get device's IRQ number
* @dev: The @mcb_device the IRQ is for
*
* Get the IRQ number of a given @mcb_device.
*/
int mcb_get_irq(struct mcb_device *dev)
{
struct mcb_bus *bus = dev->bus;
if (bus->get_irq)
return bus->get_irq(dev);
return __mcb_get_irq(dev);
}
EXPORT_SYMBOL_NS_GPL(mcb_get_irq, "MCB");
static int mcb_init(void)
{
return bus_register(&mcb_bus_type);
}
static void mcb_exit(void)
{
ida_destroy(&mcb_ida);
bus_unregister(&mcb_bus_type);
}
/* mcb must be initialized after PCI but before the chameleon drivers.
* That means we must use some initcall between subsys_initcall and
* device_initcall.
*/
fs_initcall(mcb_init);
module_exit(mcb_exit);
MODULE_DESCRIPTION("MEN Chameleon Bus Driver");
MODULE_AUTHOR("Johannes Thumshirn <johannes.thumshirn@men.de>");
MODULE_LICENSE("GPL v2");