Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

memory_accessor: implement the new memory_accessor interfaces for SPI EEPROMs

- Define new setup() hook to export the accessor
- Implement accessor methods

Moves some error checking out of the sysfs interface code into the layer
below it, which is now shared by both sysfs and memory access code.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
Cc: Jean Delvare <khali@linux-fr.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

David Brownell and committed by
Linus Torvalds
14dd1ff0 7274ec8b

+50 -14
+44 -14
drivers/misc/eeprom/at25.c
··· 30 30 31 31 struct at25_data { 32 32 struct spi_device *spi; 33 + struct memory_accessor mem; 33 34 struct mutex lock; 34 35 struct spi_eeprom chip; 35 36 struct bin_attribute bin; ··· 75 74 ssize_t status; 76 75 struct spi_transfer t[2]; 77 76 struct spi_message m; 77 + 78 + if (unlikely(offset >= at25->bin.size)) 79 + return 0; 80 + if ((offset + count) > at25->bin.size) 81 + count = at25->bin.size - offset; 82 + if (unlikely(!count)) 83 + return count; 78 84 79 85 cp = command; 80 86 *cp++ = AT25_READ; ··· 135 127 dev = container_of(kobj, struct device, kobj); 136 128 at25 = dev_get_drvdata(dev); 137 129 138 - if (unlikely(off >= at25->bin.size)) 139 - return 0; 140 - if ((off + count) > at25->bin.size) 141 - count = at25->bin.size - off; 142 - if (unlikely(!count)) 143 - return count; 144 - 145 130 return at25_ee_read(at25, buf, off, count); 146 131 } 147 132 ··· 146 145 unsigned written = 0; 147 146 unsigned buf_size; 148 147 u8 *bounce; 148 + 149 + if (unlikely(off >= at25->bin.size)) 150 + return -EFBIG; 151 + if ((off + count) > at25->bin.size) 152 + count = at25->bin.size - off; 153 + if (unlikely(!count)) 154 + return count; 149 155 150 156 /* Temp buffer starts with command and address */ 151 157 buf_size = at25->chip.page_size; ··· 261 253 dev = container_of(kobj, struct device, kobj); 262 254 at25 = dev_get_drvdata(dev); 263 255 264 - if (unlikely(off >= at25->bin.size)) 265 - return -EFBIG; 266 - if ((off + count) > at25->bin.size) 267 - count = at25->bin.size - off; 268 - if (unlikely(!count)) 269 - return count; 270 - 271 256 return at25_ee_write(at25, buf, off, count); 257 + } 258 + 259 + /*-------------------------------------------------------------------------*/ 260 + 261 + /* Let in-kernel code access the eeprom data. */ 262 + 263 + static ssize_t at25_mem_read(struct memory_accessor *mem, char *buf, 264 + off_t offset, size_t count) 265 + { 266 + struct at25_data *at25 = container_of(mem, struct at25_data, mem); 267 + 268 + return at25_ee_read(at25, buf, offset, count); 269 + } 270 + 271 + static ssize_t at25_mem_write(struct memory_accessor *mem, char *buf, 272 + off_t offset, size_t count) 273 + { 274 + struct at25_data *at25 = container_of(mem, struct at25_data, mem); 275 + 276 + return at25_ee_write(at25, buf, offset, count); 272 277 } 273 278 274 279 /*-------------------------------------------------------------------------*/ ··· 338 317 at25->addrlen = addrlen; 339 318 340 319 /* Export the EEPROM bytes through sysfs, since that's convenient. 320 + * And maybe to other kernel code; it might hold a board's Ethernet 321 + * address, or board-specific calibration data generated on the 322 + * manufacturing floor. 323 + * 341 324 * Default to root-only access to the data; EEPROMs often hold data 342 325 * that's sensitive for read and/or write, like ethernet addresses, 343 326 * security codes, board-specific manufacturing calibrations, etc. ··· 349 324 at25->bin.attr.name = "eeprom"; 350 325 at25->bin.attr.mode = S_IRUSR; 351 326 at25->bin.read = at25_bin_read; 327 + at25->mem.read = at25_mem_read; 352 328 353 329 at25->bin.size = at25->chip.byte_len; 354 330 if (!(chip->flags & EE_READONLY)) { 355 331 at25->bin.write = at25_bin_write; 356 332 at25->bin.attr.mode |= S_IWUSR; 333 + at25->mem.write = at25_mem_write; 357 334 } 358 335 359 336 err = sysfs_create_bin_file(&spi->dev.kobj, &at25->bin); 360 337 if (err) 361 338 goto fail; 339 + 340 + if (chip->setup) 341 + chip->setup(&at25->mem, chip->context); 362 342 363 343 dev_info(&spi->dev, "%Zd %s %s eeprom%s, pagesize %u\n", 364 344 (at25->bin.size < 1024)
+6
include/linux/spi/eeprom.h
··· 1 1 #ifndef __LINUX_SPI_EEPROM_H 2 2 #define __LINUX_SPI_EEPROM_H 3 3 4 + #include <linux/memory.h> 5 + 4 6 /* 5 7 * Put one of these structures in platform_data for SPI EEPROMS handled 6 8 * by the "at25" driver. On SPI, most EEPROMS understand the same core ··· 19 17 #define EE_ADDR2 0x0002 /* 16 bit addrs */ 20 18 #define EE_ADDR3 0x0004 /* 24 bit addrs */ 21 19 #define EE_READONLY 0x0008 /* disallow writes */ 20 + 21 + /* for exporting this chip's data to other kernel code */ 22 + void (*setup)(struct memory_accessor *mem, void *context); 23 + void *context; 22 24 }; 23 25 24 26 #endif /* __LINUX_SPI_EEPROM_H */