Linux Audio

Check our new training course

Loading...
v4.17
  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_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}
v4.10.11
  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}