1
2
3
4
5
6
7
8
9
10#include <linux/kernel.h>
11#include <linux/slab.h>
12#include <linux/fmc.h>
13#include <linux/ipmi-fru.h>
14
15
16void *fru_alloc(size_t size)
17{
18 return kzalloc(size, GFP_KERNEL);
19}
20
21
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
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;
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
50 return matched;
51}
52
53
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
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
72 if (!fmc->eeprom)
73 return 0;
74
75 dev_info(fmc->hwdev, "mezzanine %i\n", fmc->slot_id);
76
77
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
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;
106}
107
108
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