019-4-nvmem-Add-backwards-compatibility-support-for-older-EEPROM-drivers.patch 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. From b6c217ab9be6895384cf0b284ace84ad79e5c53b Mon Sep 17 00:00:00 2001
  2. From: Andrew Lunn <andrew@lunn.ch>
  3. Date: Fri, 26 Feb 2016 20:59:19 +0100
  4. Subject: nvmem: Add backwards compatibility support for older EEPROM drivers.
  5. Older drivers made an 'eeprom' file available in the /sys device
  6. directory. Have the NVMEM core provide this to retain backwards
  7. compatibility.
  8. Signed-off-by: Andrew Lunn <andrew@lunn.ch>
  9. Acked-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
  10. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  11. ---
  12. drivers/nvmem/core.c | 84 ++++++++++++++++++++++++++++++++++++++----
  13. include/linux/nvmem-provider.h | 4 +-
  14. 2 files changed, 79 insertions(+), 9 deletions(-)
  15. --- a/drivers/nvmem/core.c
  16. +++ b/drivers/nvmem/core.c
  17. @@ -38,8 +38,13 @@ struct nvmem_device {
  18. int users;
  19. size_t size;
  20. bool read_only;
  21. + int flags;
  22. + struct bin_attribute eeprom;
  23. + struct device *base_dev;
  24. };
  25. +#define FLAG_COMPAT BIT(0)
  26. +
  27. struct nvmem_cell {
  28. const char *name;
  29. int offset;
  30. @@ -56,16 +61,26 @@ static DEFINE_IDA(nvmem_ida);
  31. static LIST_HEAD(nvmem_cells);
  32. static DEFINE_MUTEX(nvmem_cells_mutex);
  33. +#ifdef CONFIG_DEBUG_LOCK_ALLOC
  34. +static struct lock_class_key eeprom_lock_key;
  35. +#endif
  36. +
  37. #define to_nvmem_device(d) container_of(d, struct nvmem_device, dev)
  38. static ssize_t bin_attr_nvmem_read(struct file *filp, struct kobject *kobj,
  39. struct bin_attribute *attr,
  40. char *buf, loff_t pos, size_t count)
  41. {
  42. - struct device *dev = container_of(kobj, struct device, kobj);
  43. - struct nvmem_device *nvmem = to_nvmem_device(dev);
  44. + struct device *dev;
  45. + struct nvmem_device *nvmem;
  46. int rc;
  47. + if (attr->private)
  48. + dev = attr->private;
  49. + else
  50. + dev = container_of(kobj, struct device, kobj);
  51. + nvmem = to_nvmem_device(dev);
  52. +
  53. /* Stop the user from reading */
  54. if (pos >= nvmem->size)
  55. return 0;
  56. @@ -90,10 +105,16 @@ static ssize_t bin_attr_nvmem_write(stru
  57. struct bin_attribute *attr,
  58. char *buf, loff_t pos, size_t count)
  59. {
  60. - struct device *dev = container_of(kobj, struct device, kobj);
  61. - struct nvmem_device *nvmem = to_nvmem_device(dev);
  62. + struct device *dev;
  63. + struct nvmem_device *nvmem;
  64. int rc;
  65. + if (attr->private)
  66. + dev = attr->private;
  67. + else
  68. + dev = container_of(kobj, struct device, kobj);
  69. + nvmem = to_nvmem_device(dev);
  70. +
  71. /* Stop the user from writing */
  72. if (pos >= nvmem->size)
  73. return 0;
  74. @@ -349,6 +370,43 @@ err:
  75. return rval;
  76. }
  77. +/*
  78. + * nvmem_setup_compat() - Create an additional binary entry in
  79. + * drivers sys directory, to be backwards compatible with the older
  80. + * drivers/misc/eeprom drivers.
  81. + */
  82. +static int nvmem_setup_compat(struct nvmem_device *nvmem,
  83. + const struct nvmem_config *config)
  84. +{
  85. + int rval;
  86. +
  87. + if (!config->base_dev)
  88. + return -EINVAL;
  89. +
  90. + if (nvmem->read_only)
  91. + nvmem->eeprom = bin_attr_ro_root_nvmem;
  92. + else
  93. + nvmem->eeprom = bin_attr_rw_root_nvmem;
  94. + nvmem->eeprom.attr.name = "eeprom";
  95. + nvmem->eeprom.size = nvmem->size;
  96. +#ifdef CONFIG_DEBUG_LOCK_ALLOC
  97. + nvmem->eeprom.attr.key = &eeprom_lock_key;
  98. +#endif
  99. + nvmem->eeprom.private = &nvmem->dev;
  100. + nvmem->base_dev = config->base_dev;
  101. +
  102. + rval = device_create_bin_file(nvmem->base_dev, &nvmem->eeprom);
  103. + if (rval) {
  104. + dev_err(&nvmem->dev,
  105. + "Failed to create eeprom binary file %d\n", rval);
  106. + return rval;
  107. + }
  108. +
  109. + nvmem->flags |= FLAG_COMPAT;
  110. +
  111. + return 0;
  112. +}
  113. +
  114. /**
  115. * nvmem_register() - Register a nvmem device for given nvmem_config.
  116. * Also creates an binary entry in /sys/bus/nvmem/devices/dev-name/nvmem
  117. @@ -416,16 +474,23 @@ struct nvmem_device *nvmem_register(cons
  118. dev_dbg(&nvmem->dev, "Registering nvmem device %s\n", config->name);
  119. rval = device_add(&nvmem->dev);
  120. - if (rval) {
  121. - ida_simple_remove(&nvmem_ida, nvmem->id);
  122. - kfree(nvmem);
  123. - return ERR_PTR(rval);
  124. + if (rval)
  125. + goto out;
  126. +
  127. + if (config->compat) {
  128. + rval = nvmem_setup_compat(nvmem, config);
  129. + if (rval)
  130. + goto out;
  131. }
  132. if (config->cells)
  133. nvmem_add_cells(nvmem, config);
  134. return nvmem;
  135. +out:
  136. + ida_simple_remove(&nvmem_ida, nvmem->id);
  137. + kfree(nvmem);
  138. + return ERR_PTR(rval);
  139. }
  140. EXPORT_SYMBOL_GPL(nvmem_register);
  141. @@ -445,6 +510,9 @@ int nvmem_unregister(struct nvmem_device
  142. }
  143. mutex_unlock(&nvmem_mutex);
  144. + if (nvmem->flags & FLAG_COMPAT)
  145. + device_remove_bin_file(nvmem->base_dev, &nvmem->eeprom);
  146. +
  147. nvmem_device_remove_all_cells(nvmem);
  148. device_del(&nvmem->dev);
  149. --- a/include/linux/nvmem-provider.h
  150. +++ b/include/linux/nvmem-provider.h
  151. @@ -24,6 +24,9 @@ struct nvmem_config {
  152. int ncells;
  153. bool read_only;
  154. bool root_only;
  155. + /* To be only used by old driver/misc/eeprom drivers */
  156. + bool compat;
  157. + struct device *base_dev;
  158. };
  159. #if IS_ENABLED(CONFIG_NVMEM)
  160. @@ -44,5 +47,4 @@ static inline int nvmem_unregister(struc
  161. }
  162. #endif /* CONFIG_NVMEM */
  163. -
  164. #endif /* ifndef _LINUX_NVMEM_PROVIDER_H */