fmc-match.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  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. /* The fru parser is both user and kernel capable: it needs alloc */
  15. void *fru_alloc(size_t size)
  16. {
  17. return kzalloc(size, GFP_KERNEL);
  18. }
  19. /* The actual match function */
  20. int fmc_match(struct device *dev, struct device_driver *drv)
  21. {
  22. struct fmc_driver *fdrv = to_fmc_driver(drv);
  23. struct fmc_device *fdev = to_fmc_device(dev);
  24. struct fmc_fru_id *fid;
  25. int i, matched = 0;
  26. /* This currently only matches the EEPROM (FRU id) */
  27. fid = fdrv->id_table.fru_id;
  28. if (!fid) {
  29. dev_warn(&fdev->dev, "Driver has no ID: matches all\n");
  30. matched = 1;
  31. } else {
  32. if (!fdev->id.manufacturer || !fdev->id.product_name)
  33. return 0; /* the device has no FRU information */
  34. for (i = 0; i < fdrv->id_table.fru_id_nr; i++, fid++) {
  35. if (fid->manufacturer &&
  36. strcmp(fid->manufacturer, fdev->id.manufacturer))
  37. continue;
  38. if (fid->product_name &&
  39. strcmp(fid->product_name, fdev->id.product_name))
  40. continue;
  41. matched = 1;
  42. break;
  43. }
  44. }
  45. /* FIXME: match SDB contents */
  46. return matched;
  47. }
  48. /* This function creates ID info for a newly registered device */
  49. int fmc_fill_id_info(struct fmc_device *fmc)
  50. {
  51. struct fru_common_header *h;
  52. struct fru_board_info_area *bia;
  53. int ret, allocated = 0;
  54. /* If we know the eeprom length, try to read it off the device */
  55. if (fmc->eeprom_len && !fmc->eeprom) {
  56. fmc->eeprom = kzalloc(fmc->eeprom_len, GFP_KERNEL);
  57. if (!fmc->eeprom)
  58. return -ENOMEM;
  59. allocated = 1;
  60. ret = fmc->op->read_ee(fmc, 0, fmc->eeprom, fmc->eeprom_len);
  61. if (ret < 0)
  62. goto out;
  63. }
  64. /* If no eeprom, continue with other matches */
  65. if (!fmc->eeprom)
  66. return 0;
  67. dev_info(fmc->hwdev, "mezzanine %i\n", fmc->slot_id); /* header */
  68. /* So we have the eeprom: parse the FRU part (if any) */
  69. h = (void *)fmc->eeprom;
  70. if (h->format != 1) {
  71. pr_info(" EEPROM has no FRU information\n");
  72. goto out;
  73. }
  74. if (!fru_header_cksum_ok(h)) {
  75. pr_info(" FRU: wrong header checksum\n");
  76. goto out;
  77. }
  78. bia = fru_get_board_area(h);
  79. if (!fru_bia_cksum_ok(bia)) {
  80. pr_info(" FRU: wrong board area checksum\n");
  81. goto out;
  82. }
  83. fmc->id.manufacturer = fru_get_board_manufacturer(h);
  84. fmc->id.product_name = fru_get_product_name(h);
  85. pr_info(" Manufacturer: %s\n", fmc->id.manufacturer);
  86. pr_info(" Product name: %s\n", fmc->id.product_name);
  87. /* Create the short name (FIXME: look in sdb as well) */
  88. fmc->mezzanine_name = kstrdup(fmc->id.product_name, GFP_KERNEL);
  89. out:
  90. if (allocated) {
  91. kfree(fmc->eeprom);
  92. fmc->eeprom = NULL;
  93. }
  94. return 0; /* no error: let other identification work */
  95. }
  96. /* Some ID data is allocated using fru_alloc() above, so release it */
  97. void fmc_free_id_info(struct fmc_device *fmc)
  98. {
  99. kfree(fmc->mezzanine_name);
  100. kfree(fmc->id.manufacturer);
  101. kfree(fmc->id.product_name);
  102. }