1 // SPDX-License-Identifier: GPL-2.0-or-later
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.
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
;
28 /* This currently only matches the EEPROM (FRU id) */
29 fid
= fdrv
->id_table
.fru_id
;
31 dev_warn(&fdev
->dev
, "Driver has no ID: matches all\n");
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
))
40 if (fid
->product_name
&&
41 strcmp(fid
->product_name
, fdev
->id
.product_name
))
48 /* FIXME: match SDB contents */
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
);
65 ret
= fmc_read_ee(fmc
, 0, fmc
->eeprom
, fmc
->eeprom_len
);
70 /* If no eeprom, continue with other matches */
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
;
79 pr_info(" EEPROM has no FRU information\n");
82 if (!fru_header_cksum_ok(h
)) {
83 pr_info(" FRU: wrong header checksum\n");
86 bia
= fru_get_board_area(h
);
87 if (!fru_bia_cksum_ok(bia
)) {
88 pr_info(" FRU: wrong board area checksum\n");
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
);
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
);