601-of_net-add-mac-address-ascii-support.patch 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. From: Yousong Zhou <yszhou4tech@gmail.com>
  2. Subject: [PATCH] of: net: add nvmem cell mac-address-ascii support
  3. This is needed for devices with mac address stored in ascii format,
  4. e.g. HiWiFi HC6361 to be ported in the following patch.
  5. Submitted-by: Yousong Zhou <yszhou4tech@gmail.com>
  6. ---
  7. net/core/of_net.c | 83 ++++++++++++------
  8. 1 files changed, 72 insertions(+), 11 deletions(-)
  9. --- a/net/core/of_net.c
  10. +++ b/net/core/of_net.c
  11. @@ -57,13 +57,70 @@ static int of_get_mac_addr(struct device
  12. return -ENODEV;
  13. }
  14. +static void *nvmem_cell_get_mac_address(struct nvmem_cell *cell)
  15. +{
  16. + size_t len;
  17. + void *mac;
  18. +
  19. + mac = nvmem_cell_read(cell, &len);
  20. + if (IS_ERR(mac))
  21. + return mac;
  22. + if (len != ETH_ALEN) {
  23. + kfree(mac);
  24. + return ERR_PTR(-EINVAL);
  25. + }
  26. + return mac;
  27. +}
  28. +
  29. +static void *nvmem_cell_get_mac_address_ascii(struct nvmem_cell *cell)
  30. +{
  31. + size_t len;
  32. + int ret;
  33. + void *mac_ascii;
  34. + u8 *mac;
  35. +
  36. + mac_ascii = nvmem_cell_read(cell, &len);
  37. + if (IS_ERR(mac_ascii))
  38. + return mac_ascii;
  39. + if (len != ETH_ALEN*2+5) {
  40. + kfree(mac_ascii);
  41. + return ERR_PTR(-EINVAL);
  42. + }
  43. + mac = kmalloc(ETH_ALEN, GFP_KERNEL);
  44. + if (!mac) {
  45. + kfree(mac_ascii);
  46. + return ERR_PTR(-ENOMEM);
  47. + }
  48. + ret = sscanf(mac_ascii, "%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx",
  49. + &mac[0], &mac[1], &mac[2],
  50. + &mac[3], &mac[4], &mac[5]);
  51. + kfree(mac_ascii);
  52. + if (ret == ETH_ALEN)
  53. + return mac;
  54. + kfree(mac);
  55. + return ERR_PTR(-EINVAL);
  56. +}
  57. +
  58. +static struct nvmem_cell_mac_address_property {
  59. + char *name;
  60. + void *(*read)(struct nvmem_cell *);
  61. +} nvmem_cell_mac_address_properties[] = {
  62. + {
  63. + .name = "mac-address",
  64. + .read = nvmem_cell_get_mac_address,
  65. + }, {
  66. + .name = "mac-address-ascii",
  67. + .read = nvmem_cell_get_mac_address_ascii,
  68. + },
  69. +};
  70. +
  71. static int of_get_mac_addr_nvmem(struct device_node *np, u8 *addr)
  72. {
  73. struct platform_device *pdev = of_find_device_by_node(np);
  74. + struct nvmem_cell_mac_address_property *property;
  75. struct nvmem_cell *cell;
  76. const void *mac;
  77. - size_t len;
  78. - int ret;
  79. + int ret, i;
  80. /* Try lookup by device first, there might be a nvmem_cell_lookup
  81. * associated with a given device.
  82. @@ -74,17 +131,26 @@ static int of_get_mac_addr_nvmem(struct
  83. return ret;
  84. }
  85. - cell = of_nvmem_cell_get(np, "mac-address");
  86. + for (i = 0; i < ARRAY_SIZE(nvmem_cell_mac_address_properties); i++) {
  87. + property = &nvmem_cell_mac_address_properties[i];
  88. + cell = of_nvmem_cell_get(np, property->name);
  89. + /* For -EPROBE_DEFER don't try other properties.
  90. + * We'll get back to this one.
  91. + */
  92. + if (!IS_ERR(cell) || PTR_ERR(cell) == -EPROBE_DEFER)
  93. + break;
  94. + }
  95. +
  96. if (IS_ERR(cell))
  97. return PTR_ERR(cell);
  98. - mac = nvmem_cell_read(cell, &len);
  99. + mac = property->read(cell);
  100. nvmem_cell_put(cell);
  101. if (IS_ERR(mac))
  102. return PTR_ERR(mac);
  103. - if (len != ETH_ALEN || !is_valid_ether_addr(mac)) {
  104. + if (!is_valid_ether_addr(mac)) {
  105. kfree(mac);
  106. return -EINVAL;
  107. }