linux/drivers/fmc/fmc-match.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2012 CERN (www.cern.ch)
   3 * Author: Alessandro Rubini <rubini@gnudd.com>
   4 *
   5 * Released according to the GNU GPL, version 2 or any later version.
   6 *
   7 * This work is part of the White Rabbit project, a research effort led
   8 * by CERN, the European Institute for Nuclear Research.
   9 */
  10#include <linux/kernel.h>
  11#include <linux/slab.h>
  12#include <linux/fmc.h>
  13#include <linux/ipmi-fru.h>
  14
  15/* The fru parser is both user and kernel capable: it needs alloc */
  16void *fru_alloc(size_t size)
  17{
  18        return kzalloc(size, GFP_KERNEL);
  19}
  20
  21/* The actual match function */
  22int fmc_match(struct device *dev, struct device_driver *drv)
  23{
  24        struct fmc_driver *fdrv = to_fmc_driver(drv);
  25        struct fmc_device *fdev = to_fmc_device(dev);
  26        struct fmc_fru_id *fid;
  27        int i, matched = 0;
  28
  29        /* This currently only matches the EEPROM (FRU id) */
  30        fid = fdrv->id_table.fru_id;
  31        if (!fid) {
  32                dev_warn(&fdev->dev, "Driver has no ID: matches all\n");
  33                matched = 1;
  34        } else {
  35                if (!fdev->id.manufacturer || !fdev->id.product_name)
  36                        return 0; /* the device has no FRU information */
  37                for (i = 0; i < fdrv->id_table.fru_id_nr; i++, fid++) {
  38                        if (fid->manufacturer &&
  39                            strcmp(fid->manufacturer, fdev->id.manufacturer))
  40                                continue;
  41                        if (fid->product_name &&
  42                            strcmp(fid->product_name, fdev->id.product_name))
  43                                continue;
  44                        matched = 1;
  45                        break;
  46                }
  47        }
  48
  49        /* FIXME: match SDB contents */
  50        return matched;
  51}
  52
  53/* This function creates ID info for a newly registered device */
  54int fmc_fill_id_info(struct fmc_device *fmc)
  55{
  56        struct fru_common_header *h;
  57        struct fru_board_info_area *bia;
  58        int ret, allocated = 0;
  59
  60        /* If we know the eeprom length, try to read it off the device */
  61        if (fmc->eeprom_len && !fmc->eeprom) {
  62                fmc->eeprom = kzalloc(fmc->eeprom_len, GFP_KERNEL);
  63                if (!fmc->eeprom)
  64                        return -ENOMEM;
  65                allocated = 1;
  66                ret = fmc->op->read_ee(fmc, 0, fmc->eeprom, fmc->eeprom_len);
  67                if (ret < 0)
  68                        goto out;
  69        }
  70
  71        /* If no eeprom, continue with other matches */
  72        if (!fmc->eeprom)
  73                return 0;
  74
  75        dev_info(fmc->hwdev, "mezzanine %i\n", fmc->slot_id); /* header */
  76
  77        /* So we have the eeprom: parse the FRU part (if any) */
  78        h = (void *)fmc->eeprom;
  79        if (h->format != 1) {
  80                pr_info("      EEPROM has no FRU information\n");
  81                goto out;
  82        }
  83        if (!fru_header_cksum_ok(h)) {
  84                pr_info("      FRU: wrong header checksum\n");
  85                goto out;
  86        }
  87        bia = fru_get_board_area(h);
  88        if (!fru_bia_cksum_ok(bia)) {
  89                pr_info("      FRU: wrong board area checksum\n");
  90                goto out;
  91        }
  92        fmc->id.manufacturer = fru_get_board_manufacturer(h);
  93        fmc->id.product_name = fru_get_product_name(h);
  94        pr_info("      Manufacturer: %s\n", fmc->id.manufacturer);
  95        pr_info("      Product name: %s\n", fmc->id.product_name);
  96
  97        /* Create the short name (FIXME: look in sdb as well) */
  98        fmc->mezzanine_name = kstrdup(fmc->id.product_name, GFP_KERNEL);
  99
 100out:
 101        if (allocated) {
 102                kfree(fmc->eeprom);
 103                fmc->eeprom = NULL;
 104        }
 105        return 0; /* no error: let other identification work */
 106}
 107
 108/* Some ID data is allocated using fru_alloc() above, so release it */
 109void fmc_free_id_info(struct fmc_device *fmc)
 110{
 111        kfree(fmc->mezzanine_name);
 112        kfree(fmc->id.manufacturer);
 113        kfree(fmc->id.product_name);
 114}
 115