Commit 18b4b1d1 authored by Alessandro Rubini's avatar Alessandro Rubini

kernel/fmc-core: implement register_n and unregister_n

Additionally, this adds some checks that were missing. A device without
device_id is now refused, instead of receiving a sequential number.
Signed-off-by: Alessandro Rubini's avatarAlessandro Rubini <rubini@gnudd.com>
parent 6a5bfab5
......@@ -9,6 +9,7 @@
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/fmc.h>
......@@ -94,17 +95,60 @@ void fmc_driver_unregister(struct fmc_driver *drv)
}
EXPORT_SYMBOL(fmc_driver_unregister);
/* When a device is registered, we must read the eeprom and parse FRU */
int fmc_device_register(struct fmc_device *fmc)
/*
* When a device set is registered, all eeproms must be read
*and all FRU must be parsed
*/
int fmc_device_register_n(struct fmc_device *fmcs, int n)
{
static int fmc_index; /* a "unique" name for lame devices */
struct fmc_device *fmc, **devarray;
uint32_t device_id;
int ret;
int i, ret = 0;
/* Check the version of the first data structure (function prints) */
if (fmc_check_version(fmcs->version, fmcs->carrier_name))
return -EINVAL;
if (fmc_check_version(fmc->version, fmc->carrier_name))
devarray = kmalloc(n * sizeof(*devarray),GFP_KERNEL);
if (!devarray) return -ENOMEM;
/* Make all other checks before continuing, for all devices */
for (i = 0, fmc = fmcs; i < n; i++, fmc++) {
if (!fmc->hwdev) {
pr_err("%s: device has no hwdev pointer\n", __func__);
return -EINVAL;
}
if (!fmc->eeprom) {
dev_err(fmc->hwdev, "no eeprom provided to fmc bus\n");
ret = -EINVAL;
}
if (!fmc->eeprom_addr) {
dev_err(fmc->hwdev, "eeprom_addr must be set\n");
ret = -EINVAL;
}
if (!fmc->carrier_name || !fmc->carrier_data || \
!fmc->device_id) {
dev_err(fmc->hwdev, "carrier name and data, and dev_id"
"must all be set\n");
ret = -EINVAL;
}
if(ret)
break;
/* make sure it is not initialized, or it complains */
fmc->nr_slots = n;
devarray[i] = fmc;
}
if (ret) {
kfree(devarray);
return ret;
}
/* Validation is ok. Now init and register the devices */
for (i = 0, fmc = fmcs; i < n; i++, fmc++) {
fmc->devarray = devarray;
/* make sure dev is not initialized, or it complains */
memset(&fmc->dev.kobj, 0, sizeof(struct kobject));
device_initialize(&fmc->dev);
......@@ -118,12 +162,8 @@ int fmc_device_register(struct fmc_device *fmc)
fmc->dev.bus = &fmc_bus_type;
/* The name is from mezzanine info or carrier info. Or 0,1,2.. */
/* Name from mezzanine info or carrier info. Or 0,1,2.. */
device_id = fmc->device_id;
if (!device_id) {
dev_warn(fmc->hwdev, "No device_id filled, using index\n");
device_id = fmc_index++;
}
if (!fmc->mezzanine_name) {
dev_warn(fmc->hwdev, "No mezzanine_name found\n");
dev_set_name(&fmc->dev, "fmc-%04x", device_id);
......@@ -136,20 +176,56 @@ int fmc_device_register(struct fmc_device *fmc)
dev_err(fmc->hwdev, "Failed in registering \"%s\"\n",
fmc->dev.kobj.name);
fmc_free_id_info(fmc);
return ret;
goto out;
}
}
return 0;
out:
for (i--, fmc--; i >= 0; i--, fmc--) {
device_del(&fmc->dev);
fmc_free_id_info(fmc);
put_device(&fmc->dev);
}
kfree(fmcs->devarray);
for (i = 0, fmc = fmcs; i < n; i++, fmc++)
fmc->devarray = NULL;
fmc_free_id_info(fmc);
return ret;
}
EXPORT_SYMBOL(fmc_device_register_n);
int fmc_device_register(struct fmc_device *fmc)
{
return fmc_device_register_n(fmc, 1);
}
EXPORT_SYMBOL(fmc_device_register);
void fmc_device_unregister(struct fmc_device *fmc)
void fmc_device_unregister_n(struct fmc_device *fmcs, int n)
{
struct fmc_device *fmc;
int i;
for (i = 0, fmc = fmcs; i < n; i++, fmc++) {
device_del(&fmc->dev);
fmc_free_id_info(fmc);
put_device(&fmc->dev);
}
/* Then, free the locally-allocated stuff */
for (i = 0, fmc = fmcs; i < n; i++, fmc++) {
if (i == 0)
kfree(fmc->devarray);
fmc->devarray = NULL;
}
}
EXPORT_SYMBOL(fmc_device_unregister);
EXPORT_SYMBOL(fmc_device_unregister_n);
void fmc_device_unregister(struct fmc_device *fmc)
{
fmc_device_unregister_n(fmc, 1);
}
EXPORT_SYMBOL(fmc_device_unregister);
/* Init and exit are trivial */
static int fmc_init(void)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment