Commit 1f650869 authored by Alessandro Rubini's avatar Alessandro Rubini

fmc bus and users: add fmc_version support

Signed-off-by: Alessandro Rubini's avatarAlessandro Rubini <rubini@gnudd.com>
parent 1f5d9c08
...@@ -112,13 +112,19 @@ driver. For this reason the device structure includes a complete copy ...@@ -112,13 +112,19 @@ driver. For this reason the device structure includes a complete copy
of the EEPROM (actually, the carrier driver may choose to only return of the EEPROM (actually, the carrier driver may choose to only return
the leading part of it). the leading part of it).
This is the current structure defining a device. Please note that stuff This is the current structure defining a device. Please note that all
is still being defined as I write this, so the structures are going to the machinery is in place but some details may still change in the future.
change (if in doubt, please check the header file in the repository rather For this reason, there is a version field at the beginning of the structure.
than this document): As usual, the minor number will change for compatible changes (like a new
flag) and the minor number will increase when an incompatible change
happens (for example, a change in layout of some @i{fmc} data structures).
Device writers should just set it to the
value @t{FMC_VERSION}, and be ready to get back @t{-EINVAL} at
registration time.
@smallexample @smallexample
struct fmc_device { struct fmc_device {
unsigned long version; /* to be set to FMC_VERSION */
struct fmc_device_id id; /* for the match function */ struct fmc_device_id id; /* for the match function */
struct fmc_operations *op; /* carrier-provided */ struct fmc_operations *op; /* carrier-provided */
int irq; /* according to host bus. 0 == none */ int irq; /* according to host bus. 0 == none */
......
...@@ -14,6 +14,20 @@ ...@@ -14,6 +14,20 @@
#include <linux/fmc.h> #include <linux/fmc.h>
#include "spec.h" #include "spec.h"
static int fmc_check_version(unsigned long version, const char *name)
{
if (__FMC_MAJOR(version) != FMC_MAJOR) {
pr_err("%s: \"%s\" has wrong major (has %li, expected %i)\n",
__func__, name, __FMC_MAJOR(version), FMC_MAJOR);
return -EINVAL;
}
if (__FMC_MINOR(version) != FMC_MINOR)
pr_info("%s: \"%s\" has wrong minor (has %li, expected %i)\n",
__func__, name, __FMC_MINOR(version), FMC_MINOR);
return 0;
}
static int fmc_match(struct device *dev, struct device_driver *drv) static int fmc_match(struct device *dev, struct device_driver *drv)
{ {
//struct fmc_driver *fdrv = to_fmc_driver(drv); //struct fmc_driver *fdrv = to_fmc_driver(drv);
...@@ -75,6 +89,8 @@ struct device fmc_bus = { ...@@ -75,6 +89,8 @@ struct device fmc_bus = {
/* Functions for client modules */ /* Functions for client modules */
int fmc_driver_register(struct fmc_driver *drv) int fmc_driver_register(struct fmc_driver *drv)
{ {
if (fmc_check_version(drv->version, drv->driver.name))
return -EINVAL;
drv->driver.bus = &fmc_bus_type; drv->driver.bus = &fmc_bus_type;
return driver_register(&drv->driver); return driver_register(&drv->driver);
} }
...@@ -88,6 +104,8 @@ EXPORT_SYMBOL(fmc_driver_unregister); ...@@ -88,6 +104,8 @@ EXPORT_SYMBOL(fmc_driver_unregister);
int fmc_device_register(struct fmc_device *fdev) int fmc_device_register(struct fmc_device *fdev)
{ {
if (fmc_check_version(fdev->version, fdev->carrier_name))
return -EINVAL;
device_initialize(&fdev->dev); device_initialize(&fdev->dev);
if (!fdev->dev.release) if (!fdev->dev.release)
fdev->dev.release = __fmc_release; fdev->dev.release = __fmc_release;
......
...@@ -47,6 +47,7 @@ int t_remove(struct fmc_device *fmc) ...@@ -47,6 +47,7 @@ int t_remove(struct fmc_device *fmc)
} }
static struct fmc_driver t_drv = { static struct fmc_driver t_drv = {
.version = FMC_VERSION,
.driver.name = KBUILD_MODNAME, .driver.name = KBUILD_MODNAME,
.probe = t_probe, .probe = t_probe,
.remove = t_remove, .remove = t_remove,
......
...@@ -138,6 +138,7 @@ int fwe_remove(struct fmc_device *fmc) ...@@ -138,6 +138,7 @@ int fwe_remove(struct fmc_device *fmc)
} }
static struct fmc_driver fwe_drv = { static struct fmc_driver fwe_drv = {
.version = FMC_VERSION,
.driver.name = KBUILD_MODNAME, .driver.name = KBUILD_MODNAME,
.probe = fwe_probe, .probe = fwe_probe,
.remove = fwe_remove, .remove = fwe_remove,
......
...@@ -18,6 +18,17 @@ ...@@ -18,6 +18,17 @@
struct fmc_device; struct fmc_device;
struct fmc_driver; struct fmc_driver;
/*
* This bus abstraction is developed separately from drivers, so we need
* to check the version of the data structures we receive.
*/
#define FMC_MAJOR 1
#define FMC_MINOR 0
#define FMC_VERSION ((FMC_MAJOR << 16) | FMC_MINOR)
#define __FMC_MAJOR(x) ((x) >> 16)
#define __FMC_MINOR(x) ((x) & 0xffff)
struct fmc_device_id { struct fmc_device_id {
/* FIXME: the device ID must be defined according to eeprom contents */ /* FIXME: the device ID must be defined according to eeprom contents */
uint64_t unique_id; uint64_t unique_id;
...@@ -27,6 +38,7 @@ struct fmc_device_id { ...@@ -27,6 +38,7 @@ struct fmc_device_id {
/* The driver is a pretty simple thing */ /* The driver is a pretty simple thing */
struct fmc_driver { struct fmc_driver {
unsigned long version;
struct device_driver driver; struct device_driver driver;
int (*probe)(struct fmc_device *); int (*probe)(struct fmc_device *);
int (*remove)(struct fmc_device *); int (*remove)(struct fmc_device *);
...@@ -61,6 +73,7 @@ struct fmc_operations { ...@@ -61,6 +73,7 @@ struct fmc_operations {
/* The device reports all information needed to access hw */ /* The device reports all information needed to access hw */
struct fmc_device { struct fmc_device {
unsigned long version;
unsigned long flags; unsigned long flags;
struct fmc_device_id id; /* for the match function */ struct fmc_device_id id; /* for the match function */
struct fmc_operations *op; /* carrier-provided */ struct fmc_operations *op; /* carrier-provided */
......
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