summaryrefslogtreecommitdiff
path: root/drivers/mcb
diff options
context:
space:
mode:
authorAndré Fabian Silva Delgado <emulatorman@parabola.nu>2016-09-11 04:34:46 -0300
committerAndré Fabian Silva Delgado <emulatorman@parabola.nu>2016-09-11 04:34:46 -0300
commit863981e96738983919de841ec669e157e6bdaeb0 (patch)
treed6d89a12e7eb8017837c057935a2271290907f76 /drivers/mcb
parent8dec7c70575785729a6a9e6719a955e9c545bcab (diff)
Linux-libre 4.7.1-gnupck-4.7.1-gnu
Diffstat (limited to 'drivers/mcb')
-rw-r--r--drivers/mcb/mcb-core.c116
-rw-r--r--drivers/mcb/mcb-internal.h1
-rw-r--r--drivers/mcb/mcb-parse.c15
-rw-r--r--drivers/mcb/mcb-pci.c23
4 files changed, 119 insertions, 36 deletions
diff --git a/drivers/mcb/mcb-core.c b/drivers/mcb/mcb-core.c
index a4be45107..6f2c8522e 100644
--- a/drivers/mcb/mcb-core.c
+++ b/drivers/mcb/mcb-core.c
@@ -61,21 +61,36 @@ 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;
- return mdrv->probe(mdev, found_id);
+ 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);
+
+ return ret;
}
static int 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);
return 0;
@@ -83,13 +98,67 @@ static int mcb_remove(struct device *dev)
static void mcb_shutdown(struct device *dev)
{
+ struct mcb_driver *mdrv = to_mcb_driver(dev->driver);
struct mcb_device *mdev = to_mcb_device(dev);
- struct mcb_driver *mdrv = mdev->driver;
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 struct bus_type mcb_bus_type = {
.name = "mcb",
.match = mcb_match,
@@ -99,6 +168,11 @@ static struct bus_type mcb_bus_type = {
.shutdown = mcb_shutdown,
};
+static 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
@@ -155,6 +229,7 @@ int mcb_device_register(struct mcb_bus *bus, struct mcb_device *dev)
int device_id;
device_initialize(&dev->dev);
+ mcb_bus_get(bus);
dev->dev.bus = &mcb_bus_type;
dev->dev.parent = bus->dev.parent;
dev->dev.release = mcb_release_dev;
@@ -178,6 +253,15 @@ out:
}
EXPORT_SYMBOL_GPL(mcb_device_register);
+static void mcb_free_bus(struct device *dev)
+{
+ struct mcb_bus *bus = to_mcb_bus(dev);
+
+ put_device(bus->carrier);
+ ida_simple_remove(&mcb_ida, bus->bus_nr);
+ kfree(bus);
+}
+
/**
* mcb_alloc_bus() - Allocate a new @mcb_bus
*
@@ -187,6 +271,7 @@ 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)
@@ -194,14 +279,29 @@ struct mcb_bus *mcb_alloc_bus(struct device *carrier)
bus_nr = ida_simple_get(&mcb_ida, 0, 0, GFP_KERNEL);
if (bus_nr < 0) {
- kfree(bus);
- return ERR_PTR(bus_nr);
+ rc = bus_nr;
+ goto err_free;
}
- INIT_LIST_HEAD(&bus->children);
bus->bus_nr = bus_nr;
- bus->carrier = carrier;
+ 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_free;
+
return bus;
+err_free:
+ put_device(carrier);
+ kfree(bus);
+ return ERR_PTR(rc);
}
EXPORT_SYMBOL_GPL(mcb_alloc_bus);
@@ -224,10 +324,6 @@ static void mcb_devices_unregister(struct mcb_bus *bus)
void mcb_release_bus(struct mcb_bus *bus)
{
mcb_devices_unregister(bus);
-
- ida_simple_remove(&mcb_ida, bus->bus_nr);
-
- kfree(bus);
}
EXPORT_SYMBOL_GPL(mcb_release_bus);
diff --git a/drivers/mcb/mcb-internal.h b/drivers/mcb/mcb-internal.h
index fb7493dcf..5254e0285 100644
--- a/drivers/mcb/mcb-internal.h
+++ b/drivers/mcb/mcb-internal.h
@@ -5,7 +5,6 @@
#define PCI_VENDOR_ID_MEN 0x1a88
#define PCI_DEVICE_ID_MEN_CHAMELEON 0x4d45
-#define CHAMELEON_FILENAME_LEN 12
#define CHAMELEONV2_MAGIC 0xabce
#define CHAM_HEADER_SIZE 0x200
diff --git a/drivers/mcb/mcb-parse.c b/drivers/mcb/mcb-parse.c
index b0155b05c..dbecbed0d 100644
--- a/drivers/mcb/mcb-parse.c
+++ b/drivers/mcb/mcb-parse.c
@@ -113,16 +113,11 @@ int chameleon_parse_cells(struct mcb_bus *bus, phys_addr_t mapbase,
}
p += hsize;
- pr_debug("header->revision = %d\n", header->revision);
- pr_debug("header->model = 0x%x ('%c')\n", header->model,
- header->model);
- pr_debug("header->minor = %d\n", header->minor);
- pr_debug("header->bus_type = 0x%x\n", header->bus_type);
-
-
- pr_debug("header->magic = 0x%x\n", header->magic);
- pr_debug("header->filename = \"%.*s\"\n", CHAMELEON_FILENAME_LEN,
- header->filename);
+ bus->revision = header->revision;
+ bus->model = header->model;
+ bus->minor = header->minor;
+ snprintf(bus->name, CHAMELEON_FILENAME_LEN + 1, "%s",
+ header->filename);
for_each_chameleon_cell(dtype, p) {
switch (dtype) {
diff --git a/drivers/mcb/mcb-pci.c b/drivers/mcb/mcb-pci.c
index 67d5e7d08..b15a0349c 100644
--- a/drivers/mcb/mcb-pci.c
+++ b/drivers/mcb/mcb-pci.c
@@ -35,7 +35,6 @@ static int mcb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
struct resource *res;
struct priv *priv;
int ret;
- int num_cells;
unsigned long flags;
priv = devm_kzalloc(&pdev->dev, sizeof(struct priv), GFP_KERNEL);
@@ -55,19 +54,20 @@ static int mcb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto out_disable;
}
- res = request_mem_region(priv->mapbase, CHAM_HEADER_SIZE,
- KBUILD_MODNAME);
+ res = devm_request_mem_region(&pdev->dev, priv->mapbase,
+ CHAM_HEADER_SIZE,
+ KBUILD_MODNAME);
if (!res) {
dev_err(&pdev->dev, "Failed to request PCI memory\n");
ret = -EBUSY;
goto out_disable;
}
- priv->base = ioremap(priv->mapbase, CHAM_HEADER_SIZE);
+ priv->base = devm_ioremap(&pdev->dev, priv->mapbase, CHAM_HEADER_SIZE);
if (!priv->base) {
dev_err(&pdev->dev, "Cannot ioremap\n");
ret = -ENOMEM;
- goto out_release;
+ goto out_disable;
}
flags = pci_resource_flags(pdev, 0);
@@ -75,7 +75,7 @@ static int mcb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
ret = -ENOTSUPP;
dev_err(&pdev->dev,
"IO mapped PCI devices are not supported\n");
- goto out_iounmap;
+ goto out_disable;
}
pci_set_drvdata(pdev, priv);
@@ -83,7 +83,7 @@ static int mcb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
priv->bus = mcb_alloc_bus(&pdev->dev);
if (IS_ERR(priv->bus)) {
ret = PTR_ERR(priv->bus);
- goto out_iounmap;
+ goto out_disable;
}
priv->bus->get_irq = mcb_pci_get_irq;
@@ -91,9 +91,8 @@ static int mcb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
ret = chameleon_parse_cells(priv->bus, priv->mapbase, priv->base);
if (ret < 0)
goto out_mcb_bus;
- num_cells = ret;
- dev_dbg(&pdev->dev, "Found %d cells\n", num_cells);
+ dev_dbg(&pdev->dev, "Found %d cells\n", ret);
mcb_bus_add_devices(priv->bus);
@@ -101,10 +100,6 @@ static int mcb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
out_mcb_bus:
mcb_release_bus(priv->bus);
-out_iounmap:
- iounmap(priv->base);
-out_release:
- pci_release_region(pdev, 0);
out_disable:
pci_disable_device(pdev);
return ret;
@@ -116,8 +111,6 @@ static void mcb_pci_remove(struct pci_dev *pdev)
mcb_release_bus(priv->bus);
- iounmap(priv->base);
- release_region(priv->mapbase, CHAM_HEADER_SIZE);
pci_disable_device(pdev);
}