cregit-Linux how code gets into the kernel

Release 4.7 drivers/fmc/fmc-core.c

Directory: drivers/fmc
/*
 * Copyright (C) 2012 CERN (www.cern.ch)
 * Author: Alessandro Rubini <rubini@gnudd.com>
 *
 * Released according to the GNU GPL, version 2 or any later version.
 *
 * This work is part of the White Rabbit project, a research effort led
 * by CERN, the European Institute for Nuclear Research.
 */
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/fmc.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; }

Contributors

PersonTokensPropCommitsCommitProp
alessandro rubinialessandro rubini74100.00%1100.00%
Total74100.00%1100.00%


static int fmc_uevent(struct device *dev, struct kobj_uevent_env *env) { /* struct fmc_device *fdev = to_fmc_device(dev); */ /* FIXME: The MODALIAS */ add_uevent_var(env, "MODALIAS=%s", "fmc"); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
alessandro rubinialessandro rubini30100.00%1100.00%
Total30100.00%1100.00%


static int fmc_probe(struct device *dev) { struct fmc_driver *fdrv = to_fmc_driver(dev->driver); struct fmc_device *fdev = to_fmc_device(dev); return fdrv->probe(fdev); }

Contributors

PersonTokensPropCommitsCommitProp
alessandro rubinialessandro rubini41100.00%1100.00%
Total41100.00%1100.00%


static int fmc_remove(struct device *dev) { struct fmc_driver *fdrv = to_fmc_driver(dev->driver); struct fmc_device *fdev = to_fmc_device(dev); return fdrv->remove(fdev); }

Contributors

PersonTokensPropCommitsCommitProp
alessandro rubinialessandro rubini41100.00%1100.00%
Total41100.00%1100.00%


static void fmc_shutdown(struct device *dev) { /* not implemented but mandatory */ }

Contributors

PersonTokensPropCommitsCommitProp
alessandro rubinialessandro rubini12100.00%1100.00%
Total12100.00%1100.00%

static struct bus_type fmc_bus_type = { .name = "fmc", .match = fmc_match, .uevent = fmc_uevent, .probe = fmc_probe, .remove = fmc_remove, .shutdown = fmc_shutdown, };
static void fmc_release(struct device *dev) { struct fmc_device *fmc = container_of(dev, struct fmc_device, dev); kfree(fmc); }

Contributors

PersonTokensPropCommitsCommitProp
alessandro rubinialessandro rubini31100.00%1100.00%
Total31100.00%1100.00%

/* * 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; }

Contributors

PersonTokensPropCommitsCommitProp
alessandro rubinialessandro rubini124100.00%1100.00%
Total124100.00%1100.00%


static ssize_t fmc_write_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; dev = container_of(kobj, struct device, kobj); fmc = container_of(dev, struct fmc_device, dev); return fmc->op->write_ee(fmc, off, buf, count); }

Contributors

PersonTokensPropCommitsCommitProp
alessandro rubinialessandro rubini81100.00%1100.00%
Total81100.00%1100.00%

static struct bin_attribute fmc_eeprom_attr = { .attr = { .name = "eeprom", .mode = S_IRUGO | S_IWUSR, }, .size = 8192, /* more or less standard */ .read = fmc_read_eeprom, .write = fmc_write_eeprom, }; /* * Functions for client modules follow */
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; return driver_register(&drv->driver); }

Contributors

PersonTokensPropCommitsCommitProp
alessandro rubinialessandro rubini47100.00%1100.00%
Total47100.00%1100.00%

EXPORT_SYMBOL(fmc_driver_register);
void fmc_driver_unregister(struct fmc_driver *drv) { driver_unregister(&drv->driver); }

Contributors

PersonTokensPropCommitsCommitProp
alessandro rubinialessandro rubini18100.00%1100.00%
Total18100.00%1100.00%

EXPORT_SYMBOL(fmc_driver_unregister); /* * When a device set is registered, all eeproms must be read * and all FRUs must be parsed */
int fmc_device_register_n(struct fmc_device **devs, int n) { struct fmc_device *fmc, **devarray; uint32_t device_id; int i, ret = 0; if (n < 1) return 0; /* Check the version of the first data structure (function prints) */ if (fmc_check_version(devs[0]->version, devs[0]->carrier_name)) return -EINVAL; devarray = kmemdup(devs, n * sizeof(*devs), GFP_KERNEL); if (!devarray) return -ENOMEM; /* Make all other checks before continuing, for all devices */ for (i = 0; i < n; i++) { fmc = devarray[i]; if (!fmc->hwdev) { pr_err("%s: device nr. %i has no hwdev pointer\n", __func__, i); ret = -EINVAL; break; } if (fmc->flags & FMC_DEVICE_NO_MEZZANINE) { dev_info(fmc->hwdev, "absent mezzanine in slot %d\n", fmc->slot_id); continue; } if (!fmc->eeprom) { dev_err(fmc->hwdev, "no eeprom provided for slot %i\n", fmc->slot_id); ret = -EINVAL; } if (!fmc->eeprom_addr) { dev_err(fmc->hwdev, "no eeprom_addr for slot %i\n", fmc->slot_id); ret = -EINVAL; } if (!fmc->carrier_name || !fmc->carrier_data || !fmc->device_id) { dev_err(fmc->hwdev, "deivce nr %i: carrier name, " "data or dev_id not set\n", i); ret = -EINVAL; } if (ret) break; } if (ret) { kfree(devarray); return ret; } /* Validation is ok. Now init and register the devices */ for (i = 0; i < n; i++) { fmc = devarray[i]; fmc->nr_slots = n; /* each slot must know how many are there */ fmc->devarray = devarray; device_initialize(&fmc->dev); fmc->dev.release = fmc_release; fmc->dev.parent = fmc->hwdev; /* Fill the identification stuff (may fail) */ fmc_fill_id_info(fmc); fmc->dev.bus = &fmc_bus_type; /* Name from mezzanine info or carrier info. Or 0,1,2.. */ device_id = fmc->device_id; if (!fmc->mezzanine_name) dev_set_name(&fmc->dev, "fmc-%04x", device_id); else dev_set_name(&fmc->dev, "%s-%04x", fmc->mezzanine_name, device_id); ret = device_add(&fmc->dev); if (ret < 0) { dev_err(fmc->hwdev, "Slot %i: Failed in registering " "\"%s\"\n", fmc->slot_id, fmc->dev.kobj.name); goto out; } ret = sysfs_create_bin_file(&fmc->dev.kobj, &fmc_eeprom_attr); if (ret < 0) { dev_err(&fmc->dev, "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); } return ret; }

Contributors

PersonTokensPropCommitsCommitProp
alessandro rubinialessandro rubini578100.00%2100.00%
Total578100.00%2100.00%

EXPORT_SYMBOL(fmc_device_register_n);
int fmc_device_register(struct fmc_device *fmc) { return fmc_device_register_n(&fmc, 1); }

Contributors

PersonTokensPropCommitsCommitProp
alessandro rubinialessandro rubini19100.00%1100.00%
Total19100.00%1100.00%

EXPORT_SYMBOL(fmc_device_register);
void fmc_device_unregister_n(struct fmc_device **devs, int n) { int i; if (n < 1) return; /* Free devarray first, not used by the later loop */ 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); } }

Contributors

PersonTokensPropCommitsCommitProp
alessandro rubinialessandro rubini96100.00%1100.00%
Total96100.00%1100.00%

EXPORT_SYMBOL(fmc_device_unregister_n);
void fmc_device_unregister(struct fmc_device *fmc) { fmc_device_unregister_n(&fmc, 1); }

Contributors

PersonTokensPropCommitsCommitProp
alessandro rubinialessandro rubini18100.00%1100.00%
Total18100.00%1100.00%

EXPORT_SYMBOL(fmc_device_unregister); /* Init and exit are trivial */
static int fmc_init(void) { return bus_register(&fmc_bus_type); }

Contributors

PersonTokensPropCommitsCommitProp
alessandro rubinialessandro rubini15100.00%1100.00%
Total15100.00%1100.00%


static void fmc_exit(void) { bus_unregister(&fmc_bus_type); }

Contributors

PersonTokensPropCommitsCommitProp
alessandro rubinialessandro rubini14100.00%1100.00%
Total14100.00%1100.00%

module_init(fmc_init); module_exit(fmc_exit); MODULE_LICENSE("GPL");

Overall Contributors

PersonTokensPropCommitsCommitProp
alessandro rubinialessandro rubini1384100.00%4100.00%
Total1384100.00%4100.00%
Directory: drivers/fmc
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
{% endraw %}