[coreboot-gerrit] Patch set updated for coreboot: commonlib: provide incoherent region device

Aaron Durbin (adurbin@chromium.org) gerrit at coreboot.org
Mon Dec 5 21:05:47 CET 2016


Aaron Durbin (adurbin at chromium.org) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/17716

-gerrit

commit e9918746699dfa019bcd39d9edca9d4be9cd7224
Author: Aaron Durbin <adurbin at chromium.org>
Date:   Sat Dec 3 17:08:08 2016 -0600

    commonlib: provide incoherent region device
    
    The MRC cache uses an incoherent mechanism for updating the
    cache contents in that it assumes memory mapped boot device
    access for checking against latest data for update. However,
    it uses another driver for updating the underlying storage
    area.
    
    In order to aid in moving the MRC cache over to using
    region_devices for updates provide an implementation of
    a region_device which performs reads and writes to different
    region_devices so that different drivers can be used
    transparently.
    
    BUG=chrome-os-partner:56151
    
    Change-Id: I30e858245c30cbccd6313aff5ebecd3fd98d7302
    Signed-off-by: Aaron Durbin <adurbin at chromium.org>
---
 src/commonlib/include/commonlib/region.h | 23 ++++++++++
 src/commonlib/region.c                   | 79 ++++++++++++++++++++++++++++++++
 2 files changed, 102 insertions(+)

diff --git a/src/commonlib/include/commonlib/region.h b/src/commonlib/include/commonlib/region.h
index bc3ded1..3f7d3bd 100644
--- a/src/commonlib/include/commonlib/region.h
+++ b/src/commonlib/include/commonlib/region.h
@@ -245,4 +245,27 @@ void xlate_region_device_rw_init(struct xlate_region_device *xdev,
 			      size_t sub_offset, size_t sub_size,
 			      size_t parent_size);
 
+/* This type can be used for incoherent access where the read and write
+ * operations are backed by separate drivers. An example is x86 systems
+ * with memory mapped media for reading but use a spi flash driver for
+ * writing. One needs to ensure using this object is appropriate in context. */
+struct incoherent_rdev {
+	struct region_device rdev;
+	const struct region_device *read;
+	const struct region_device *write;
+};
+
+/* Initialize an incoherent_rdev based on the region as well as the read and
+ * write rdevs. The read and write rdevs should match in size to the passed
+ * in region. If not the initialization will fail returning NULL. Otherwise
+ * the function will return a pointer to the containing region_device to
+ * be used for region operations. Therefore, the lifetime of the returned
+ * pointer matches the lifetime of the incoherent_rdev object. Likewise,
+ * the lifetime of the read and write rdev need to match the lifetime of
+ * the incoherent_rdev object. */
+const struct region_device *incoherent_rdev_init(struct incoherent_rdev *irdev,
+				const struct region *r,
+				const struct region_device *read,
+				const struct region_device *write);
+
 #endif /* _REGION_H_ */
diff --git a/src/commonlib/region.c b/src/commonlib/region.c
index ac0faf1..bf53b9d 100644
--- a/src/commonlib/region.c
+++ b/src/commonlib/region.c
@@ -437,3 +437,82 @@ const struct region_device_ops xlate_rdev_rw_ops = {
 	.writeat = xlate_writeat,
 	.eraseat = xlate_eraseat,
 };
+
+
+static void *incoherent_mmap(const struct region_device *rd, size_t offset,
+				size_t size)
+{
+	const struct incoherent_rdev *irdev;
+
+	irdev = container_of(rd, const struct incoherent_rdev, rdev);
+
+	return rdev_mmap(irdev->read, offset, size);
+}
+
+static int incoherent_munmap(const struct region_device *rd, void *mapping)
+{
+	const struct incoherent_rdev *irdev;
+
+	irdev = container_of(rd, const struct incoherent_rdev, rdev);
+
+	return rdev_munmap(irdev->read, mapping);
+}
+
+static ssize_t incoherent_readat(const struct region_device *rd, void *b,
+				size_t offset, size_t size)
+{
+	const struct incoherent_rdev *irdev;
+
+	irdev = container_of(rd, const struct incoherent_rdev, rdev);
+
+	return rdev_readat(irdev->read, b, offset, size);
+}
+
+static ssize_t incoherent_writeat(const struct region_device *rd, const void *b,
+			size_t offset, size_t size)
+{
+	const struct incoherent_rdev *irdev;
+
+	irdev = container_of(rd, const struct incoherent_rdev, rdev);
+
+	return rdev_writeat(irdev->write, b, offset, size);
+}
+
+static ssize_t incoherent_eraseat(const struct region_device *rd, size_t offset,
+				size_t size)
+{
+	const struct incoherent_rdev *irdev;
+
+	irdev = container_of(rd, const struct incoherent_rdev, rdev);
+
+	return rdev_eraseat(irdev->write, offset, size);
+}
+
+static const struct region_device_ops incoherent_rdev_ops = {
+	.mmap = incoherent_mmap,
+	.munmap = incoherent_munmap,
+	.readat = incoherent_readat,
+	.writeat = incoherent_writeat,
+	.eraseat = incoherent_eraseat,
+};
+
+const struct region_device *incoherent_rdev_init(struct incoherent_rdev *irdev,
+				const struct region *r,
+				const struct region_device *read,
+				const struct region_device *write)
+{
+	const size_t size = region_sz(r);
+
+	if (size != region_device_sz(read) || size != region_device_sz(write))
+		return NULL;
+
+	/* The region is represented as offset 0 to size. That way, the generic
+	 * rdev operations can be called on the read or write implementation
+	 * without any unnecessary translation because the offsets all start
+	 * at 0. */
+	region_device_init(&irdev->rdev, &incoherent_rdev_ops, 0, size);
+	irdev->read = read;
+	irdev->write = write;
+
+	return &irdev->rdev;
+}



More information about the coreboot-gerrit mailing list