Commit eb01ccc6 authored by Alessandro Rubini's avatar Alessandro Rubini

fmc-core: export the eeprom as a read-only binary file in sysfs

This allows easy access to the eeprom of each mezzanine. For example
I see one at /sys/bus/fmc/devices/FmcDelay1ns4cha-f001/eeprom (fakedev
with a fine-delay eeprom image).
Signed-off-by: Alessandro Rubini's avatarAlessandro Rubini <rubini@gnudd.com>
parent d9b6163e
......@@ -1672,10 +1672,25 @@ spusa.root# insmod fmc-write-eeprom.ko busid=0x0200 file=fdelay-eeprom.bin
[14126.392600] fmc_write_eeprom: probe of fmc-0001 failed with error -2
@end smallexample
@c ==========================================================================
@node Reading back the EEPROM
@section Reading back the EEPROM
In order to read back the binary content of the @sc{eeprom} of your
mezzanine device, the bus creates a read-only @i{sysfs} file called
@t{eeprom} for each mezzanine it knows about:
@smallexample
spusa.root# cd /sys/bus/fmc/devices; ls -l */eeprom
-r--r--r-- 1 root root 8192 Apr 9 16:53 FmcDelay1ns4cha-f001/eeprom
-r--r--r-- 1 root root 8192 Apr 9 17:19 fake-design-for-testing-f002/eeprom
-r--r--r-- 1 root root 8192 Apr 9 17:19 fake-design-for-testing-f003/eeprom
-r--r--r-- 1 root root 8192 Apr 9 17:19 fmc-f004/eeprom
@end smallexample
@c ==========================================================================
@node How Identification Works at Run Time
@section How Identification Works at Run Time
@c @node How Identification Works at Run Time
@c @section How Identification Works at Run Time
@c ##########################################################################
@node SDB Support
......
......@@ -74,6 +74,37 @@ static void fmc_release(struct device *dev)
kfree(fmc);
}
/*
* The eeprom is exported in sysfs, through a binary attribute
*/
static ssize_t fmc_read_eeprom(struct file *file, struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct device *dev;
struct fmc_device *fmc;
int eelen;
dev = container_of(kobj, struct device, kobj);
fmc = container_of(dev, struct fmc_device, dev);
eelen = fmc->eeprom_len;
if (off > eelen)
return -ESPIPE;
if (off == eelen)
return 0; /* EOF */
if (off + count > eelen)
count = eelen - off;
memcpy(buf, fmc->eeprom + off, count);
return count;
}
static struct bin_attribute fmc_eeprom_attr = {
.attr = { .name = "eeprom", .mode = S_IRUGO, },
.size = 8192, /* more or less standard */
.read = fmc_read_eeprom,
};
/*
* Functions for client modules follow
*/
......@@ -170,19 +201,28 @@ int fmc_device_register_n(struct fmc_device **devs, int n)
if (ret < 0) {
dev_err(fmc->hwdev, "Failed in registering \"%s\"\n",
fmc->dev.kobj.name);
fmc_free_id_info(fmc);
put_device(&fmc->dev);
goto out;
}
ret = sysfs_create_bin_file(&fmc->dev.kobj, &fmc_eeprom_attr);
if (ret < 0) {
dev_err(fmc->hwdev, "Failed in registering eeprom\n");
goto out1;
}
/* This device went well, give information to the user */
fmc_dump_eeprom(fmc);
fmc_dump_sdb(fmc);
}
return 0;
out1:
device_del(&fmc->dev);
out:
fmc_free_id_info(fmc);
put_device(&fmc->dev);
kfree(devarray);
for (i--; i >= 0; i--) {
sysfs_remove_bin_file(&devs[i]->dev.kobj, &fmc_eeprom_attr);
device_del(&devs[i]->dev);
fmc_free_id_info(devs[i]);
put_device(&devs[i]->dev);
......@@ -209,6 +249,7 @@ void fmc_device_unregister_n(struct fmc_device **devs, int n)
kfree(devs[0]->devarray);
for (i = 0; i < n; i++) {
sysfs_remove_bin_file(&devs[i]->dev.kobj, &fmc_eeprom_attr);
device_del(&devs[i]->dev);
fmc_free_id_info(devs[i]);
put_device(&devs[i]->dev);
......
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