2 * Copyright (C) 2012 CERN (www.cern.ch)
3 * Author: Alessandro Rubini <rubini@gnudd.com>
5 * Released according to the GNU GPL, version 2 or any later version.
7 * This work is part of the White Rabbit project, a research effort led
8 * by CERN, the European Institute for Nuclear Research.
10 #include <linux/kernel.h>
11 #include <linux/slab.h>
12 #include <linux/fmc.h>
13 #include <linux/ipmi-fru.h>
15 /* The fru parser is both user and kernel capable: it needs alloc */
16 void *fru_alloc(size_t size
)
18 return kzalloc(size
, GFP_KERNEL
);
21 /* The actual match function */
22 int fmc_match(struct device
*dev
, struct device_driver
*drv
)
24 struct fmc_driver
*fdrv
= to_fmc_driver(drv
);
25 struct fmc_device
*fdev
= to_fmc_device(dev
);
26 struct fmc_fru_id
*fid
;
29 /* This currently only matches the EEPROM (FRU id) */
30 fid
= fdrv
->id_table
.fru_id
;
32 dev_warn(&fdev
->dev
, "Driver has no ID: matches all\n");
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
))
41 if (fid
->product_name
&&
42 strcmp(fid
->product_name
, fdev
->id
.product_name
))
49 /* FIXME: match SDB contents */
53 /* This function creates ID info for a newly registered device */
54 int fmc_fill_id_info(struct fmc_device
*fmc
)
56 struct fru_common_header
*h
;
57 struct fru_board_info_area
*bia
;
58 int ret
, allocated
= 0;
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
);
66 ret
= fmc_read_ee(fmc
, 0, fmc
->eeprom
, fmc
->eeprom_len
);
71 /* If no eeprom, continue with other matches */
75 dev_info(fmc
->hwdev
, "mezzanine %i\n", fmc
->slot_id
); /* header */
77 /* So we have the eeprom: parse the FRU part (if any) */
78 h
= (void *)fmc
->eeprom
;
80 pr_info(" EEPROM has no FRU information\n");
83 if (!fru_header_cksum_ok(h
)) {
84 pr_info(" FRU: wrong header checksum\n");
87 bia
= fru_get_board_area(h
);
88 if (!fru_bia_cksum_ok(bia
)) {
89 pr_info(" FRU: wrong board area checksum\n");
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
);
97 /* Create the short name (FIXME: look in sdb as well) */
98 fmc
->mezzanine_name
= kstrdup(fmc
->id
.product_name
, GFP_KERNEL
);
105 return 0; /* no error: let other identification work */
108 /* Some ID data is allocated using fru_alloc() above, so release it */
109 void fmc_free_id_info(struct fmc_device
*fmc
)
111 kfree(fmc
->mezzanine_name
);
112 kfree(fmc
->id
.manufacturer
);
113 kfree(fmc
->id
.product_name
);