cregit-Linux how code gets into the kernel

Release 4.17 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>
#include <linux/fmc-sdb.h>

#include "fmc-private.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 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 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 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 Rubini41100.00%1100.00%
Total41100.00%1100.00%


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

Contributors

PersonTokensPropCommitsCommitProp
Alessandro 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 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 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 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, };
int fmc_irq_request(struct fmc_device *fmc, irq_handler_t h, char *name, int flags) { if (fmc->op->irq_request) return fmc->op->irq_request(fmc, h, name, flags); return -EPERM; }

Contributors

PersonTokensPropCommitsCommitProp
Federico Vaga48100.00%1100.00%
Total48100.00%1100.00%

EXPORT_SYMBOL(fmc_irq_request);
void fmc_irq_free(struct fmc_device *fmc) { if (fmc->op->irq_free) fmc->op->irq_free(fmc); }

Contributors

PersonTokensPropCommitsCommitProp
Federico Vaga27100.00%1100.00%
Total27100.00%1100.00%

EXPORT_SYMBOL(fmc_irq_free);
void fmc_irq_ack(struct fmc_device *fmc) { if (likely(fmc->op->irq_ack)) fmc->op->irq_ack(fmc); }

Contributors

PersonTokensPropCommitsCommitProp
Federico Vaga30100.00%1100.00%
Total30100.00%1100.00%

EXPORT_SYMBOL(fmc_irq_ack);
int fmc_validate(struct fmc_device *fmc, struct fmc_driver *drv) { if (fmc->op->validate) return fmc->op->validate(fmc, drv); return -EPERM; }

Contributors

PersonTokensPropCommitsCommitProp
Federico Vaga39100.00%1100.00%
Total39100.00%1100.00%

EXPORT_SYMBOL(fmc_validate);
int fmc_gpio_config(struct fmc_device *fmc, struct fmc_gpio *gpio, int ngpio) { if (fmc->op->gpio_config) return fmc->op->gpio_config(fmc, gpio, ngpio); return -EPERM; }

Contributors

PersonTokensPropCommitsCommitProp
Federico Vaga44100.00%1100.00%
Total44100.00%1100.00%

EXPORT_SYMBOL(fmc_gpio_config);
int fmc_read_ee(struct fmc_device *fmc, int pos, void *d, int l) { if (fmc->op->read_ee) return fmc->op->read_ee(fmc, pos, d, l); return -EPERM; }

Contributors

PersonTokensPropCommitsCommitProp
Federico Vaga48100.00%1100.00%
Total48100.00%1100.00%

EXPORT_SYMBOL(fmc_read_ee);
int fmc_write_ee(struct fmc_device *fmc, int pos, const void *d, int l) { if (fmc->op->write_ee) return fmc->op->write_ee(fmc, pos, d, l); return -EPERM; }

Contributors

PersonTokensPropCommitsCommitProp
Federico Vaga49100.00%1100.00%
Total49100.00%1100.00%

EXPORT_SYMBOL(fmc_write_ee); /* * 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 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 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_gw(struct fmc_device **devs, int n, struct fmc_gateware *gw) { 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, "device 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); if (gw) { /* * The carrier already know the bitstream to load * for this set of FMC mezzanines. */ ret = fmc->op->reprogram_raw(fmc, NULL, gw->bitstream, gw->len); if (ret) { dev_warn(fmc->hwdev, "Invalid gateware for FMC mezzanine\n"); goto out; } } 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_debug_init(fmc); } return 0; out1: device_del(&fmc->dev); out: kfree(devarray); for (i--; i >= 0; i--) { fmc_debug_exit(devs[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 Rubini56290.06%233.33%
Federico Vaga619.78%350.00%
Masanari Iida10.16%116.67%
Total624100.00%6100.00%

EXPORT_SYMBOL(fmc_device_register_n_gw);
int fmc_device_register_n(struct fmc_device **devs, int n) { return fmc_device_register_n_gw(devs, n, NULL); }

Contributors

PersonTokensPropCommitsCommitProp
Federico Vaga2395.83%150.00%
Alessandro Rubini14.17%150.00%
Total24100.00%2100.00%

EXPORT_SYMBOL(fmc_device_register_n);
int fmc_device_register_gw(struct fmc_device *fmc, struct fmc_gateware *gw) { return fmc_device_register_n_gw(&fmc, 1, gw); }

Contributors

PersonTokensPropCommitsCommitProp
Federico Vaga26100.00%1100.00%
Total26100.00%1100.00%

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

Contributors

PersonTokensPropCommitsCommitProp
Alessandro 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++) { fmc_debug_exit(devs[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 Rubini9692.31%150.00%
Federico Vaga87.69%150.00%
Total104100.00%2100.00%

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

Contributors

PersonTokensPropCommitsCommitProp
Alessandro 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 Rubini15100.00%1100.00%
Total15100.00%1100.00%


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

Contributors

PersonTokensPropCommitsCommitProp
Alessandro Rubini14100.00%1100.00%
Total14100.00%1100.00%

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

Overall Contributors

PersonTokensPropCommitsCommitProp
Alessandro Rubini136875.00%444.44%
Federico Vaga45524.95%444.44%
Masanari Iida10.05%111.11%
Total1824100.00%9100.00%
Directory: drivers/fmc
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.