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