generic: 6.12: update block NVMEM driver
authorDaniel Golle <[email protected]>
Wed, 7 May 2025 02:58:17 +0000 (03:58 +0100)
committerDaniel Golle <[email protected]>
Wed, 7 May 2025 03:44:46 +0000 (04:44 +0100)
Update block NVMEM driver based on backported OF partition support.

Note the different MMC card DT binding compared to the previous
downstream solution: Instead of having a 'partitions' subnode inside
a 'block' node, the 'partitions' node now resides directly under the
node representing the card.

In order to make references to the 'boot0' or 'boot1' hw partitions
you will have to define 'partitions-boot0' or 'partitions-boot1', and
move the NVMEM layout into a partition (you may, of course, use
'fixed-partitions' for that, and cover the whole device, if needed).

See also https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings/mmc/mmc-card.yaml?h=v6.13

Signed-off-by: Daniel Golle <[email protected]>
17 files changed:
target/linux/generic/pending-6.12/450-block-allow-setting-partition-of_node.patch [new file with mode: 0644]
target/linux/generic/pending-6.12/450-dt-bindings-block-add-basic-bindings-for-block-devic.patch [deleted file]
target/linux/generic/pending-6.12/451-block-partitions-of-assign-Device-Tree-node-to-parti.patch [new file with mode: 0644]
target/linux/generic/pending-6.12/451-block-partitions-populate-fwnode.patch [deleted file]
target/linux/generic/pending-6.12/452-block-add-support-for-notifications.patch [deleted file]
target/linux/generic/pending-6.12/452-partitions-efi-apply-Linux-code-style.patch [new file with mode: 0644]
target/linux/generic/pending-6.12/453-block-add-new-genhd-flag-GENHD_FL_NVMEM.patch [deleted file]
target/linux/generic/pending-6.12/453-partitions-efi-allow-assigning-partition-Device-Tree.patch [new file with mode: 0644]
target/linux/generic/pending-6.12/454-block-add-support-for-notifications.patch [new file with mode: 0644]
target/linux/generic/pending-6.12/454-nvmem-implement-block-NVMEM-provider.patch [deleted file]
target/linux/generic/pending-6.12/455-block-add-new-genhd-flag-GENHD_FL_NVMEM.patch [new file with mode: 0644]
target/linux/generic/pending-6.12/455-dt-bindings-mmc-mmc-card-add-block-device-nodes.patch [deleted file]
target/linux/generic/pending-6.12/456-mmc-core-set-card-fwnode_handle.patch [deleted file]
target/linux/generic/pending-6.12/456-nvmem-implement-block-NVMEM-provider.patch [new file with mode: 0644]
target/linux/generic/pending-6.12/457-mmc-block-set-GENHD_FL_NVMEM.patch [new file with mode: 0644]
target/linux/generic/pending-6.12/457-mmc-block-set-fwnode-of-disk-devices.patch [deleted file]
target/linux/generic/pending-6.12/458-mmc-block-set-GENHD_FL_NVMEM.patch [deleted file]

diff --git a/target/linux/generic/pending-6.12/450-block-allow-setting-partition-of_node.patch b/target/linux/generic/pending-6.12/450-block-allow-setting-partition-of_node.patch
new file mode 100644 (file)
index 0000000..a3c8abc
--- /dev/null
@@ -0,0 +1,123 @@
+From decc6959a423c8617e87244fd269129fc4e7d0e6 Mon Sep 17 00:00:00 2001
+From: Daniel Golle <[email protected]>
+Date: Mon, 7 Oct 2024 23:36:14 +0100
+Subject: [PATCH 1/8] block: allow setting partition of_node
+
+Allow partition parsers to set the Device Tree node for a partition by
+introducing of_put_partition() and extending struct parsed_partitions
+accordingly.
+
+As the partition information is preallocated independently of the actual
+number of partitions the additional pointer takes about 2 kiB of allocated
+memory which is worth avoiding in case CONFIG_OF is not set. This is
+achieved by only adding the corresponding field to the struct in case
+CONFIG_OF is set using #ifdef'ery.
+
+Signed-off-by: Daniel Golle <[email protected]>
+---
+ block/partitions/check.h | 16 +++++++++++++++-
+ block/partitions/core.c  | 14 +++++++++++---
+ 2 files changed, 26 insertions(+), 4 deletions(-)
+
+--- a/block/partitions/check.h
++++ b/block/partitions/check.h
+@@ -1,6 +1,7 @@
+ /* SPDX-License-Identifier: GPL-2.0 */
+ #include <linux/pagemap.h>
+ #include <linux/blkdev.h>
++#include <linux/of.h>
+ #include "../blk.h"
+ /*
+@@ -16,6 +17,9 @@ struct parsed_partitions {
+               int flags;
+               bool has_info;
+               struct partition_meta_info info;
++#ifdef CONFIG_OF
++              struct device_node *np;
++#endif
+       } *parts;
+       int next;
+       int limit;
+@@ -34,18 +38,28 @@ static inline void put_dev_sector(Sector
+ }
+ static inline void
+-put_partition(struct parsed_partitions *p, int n, sector_t from, sector_t size)
++of_put_partition(struct parsed_partitions *p, int n, sector_t from, sector_t size,
++               struct device_node *np)
+ {
+       if (n < p->limit) {
+               char tmp[1 + BDEVNAME_SIZE + 10 + 1];
+               p->parts[n].from = from;
+               p->parts[n].size = size;
++#ifdef CONFIG_OF
++              p->parts[n].np = np;
++#endif
+               snprintf(tmp, sizeof(tmp), " %s%d", p->name, n);
+               strlcat(p->pp_buf, tmp, PAGE_SIZE);
+       }
+ }
++static inline void
++put_partition(struct parsed_partitions *p, int n, sector_t from, sector_t size)
++{
++      of_put_partition(p, n, from, size, NULL);
++}
++
+ /* detection routines go here in alphabetical order: */
+ int adfspart_check_ADFS(struct parsed_partitions *state);
+ int adfspart_check_CUMANA(struct parsed_partitions *state);
+--- a/block/partitions/core.c
++++ b/block/partitions/core.c
+@@ -9,6 +9,7 @@
+ #include <linux/slab.h>
+ #include <linux/ctype.h>
+ #include <linux/vmalloc.h>
++#include <linux/device.h>
+ #include <linux/raid/detect.h>
+ #include "check.h"
+@@ -290,7 +291,8 @@ static const DEVICE_ATTR(whole_disk, 044
+  */
+ static struct block_device *add_partition(struct gendisk *disk, int partno,
+                               sector_t start, sector_t len, int flags,
+-                              struct partition_meta_info *info)
++                              struct partition_meta_info *info,
++                              struct device_node *np)
+ {
+       dev_t devt = MKDEV(0, 0);
+       struct device *ddev = disk_to_dev(disk);
+@@ -339,6 +341,7 @@ static struct block_device *add_partitio
+       pdev->class = &block_class;
+       pdev->type = &part_type;
+       pdev->parent = ddev;
++      device_set_node(pdev, of_fwnode_handle(np));
+       /* in consecutive minor range? */
+       if (bdev_partno(bdev) < disk->minors) {
+@@ -445,7 +448,7 @@ int bdev_add_partition(struct gendisk *d
+       }
+       part = add_partition(disk, partno, start, length,
+-                      ADDPART_FLAG_NONE, NULL);
++                      ADDPART_FLAG_NONE, NULL, NULL);
+       ret = PTR_ERR_OR_ZERO(part);
+ out:
+       mutex_unlock(&disk->open_mutex);
+@@ -559,8 +562,13 @@ static bool blk_add_partition(struct gen
+               size = get_capacity(disk) - from;
+       }
++#ifdef CONFIG_OF
+       part = add_partition(disk, p, from, size, state->parts[p].flags,
+-                           &state->parts[p].info);
++                           &state->parts[p].info, state->parts[p].np);
++#else
++      part = add_partition(disk, p, from, size, state->parts[p].flags,
++                           &state->parts[p].info, NULL);
++#endif
+       if (IS_ERR(part)) {
+               if (PTR_ERR(part) != -ENXIO) {
+                       printk(KERN_ERR " %s: p%d could not be added: %pe\n",
diff --git a/target/linux/generic/pending-6.12/450-dt-bindings-block-add-basic-bindings-for-block-devic.patch b/target/linux/generic/pending-6.12/450-dt-bindings-block-add-basic-bindings-for-block-devic.patch
deleted file mode 100644 (file)
index 9089ce6..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-From 3245921a87154bdfbe7a55d743ea62dd559a8fb0 Mon Sep 17 00:00:00 2001
-From: Daniel Golle <[email protected]>
-Date: Thu, 30 May 2024 03:13:09 +0100
-Subject: [PATCH 1/9] dt-bindings: block: add basic bindings for block devices
-
-Add bindings for block devices which are used to allow referencing
-nvmem bits on them.
-
-Signed-off-by: Daniel Golle <[email protected]>
----
- .../bindings/block/block-device.yaml          | 22 ++++++++
- .../devicetree/bindings/block/partition.yaml  | 51 +++++++++++++++++++
- .../devicetree/bindings/block/partitions.yaml | 20 ++++++++
- 3 files changed, 93 insertions(+)
- create mode 100644 Documentation/devicetree/bindings/block/block-device.yaml
- create mode 100644 Documentation/devicetree/bindings/block/partition.yaml
- create mode 100644 Documentation/devicetree/bindings/block/partitions.yaml
-
---- /dev/null
-+++ b/Documentation/devicetree/bindings/block/block-device.yaml
-@@ -0,0 +1,22 @@
-+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
-+%YAML 1.2
-+---
-+$id: http://devicetree.org/schemas/block/block-device.yaml#
-+$schema: http://devicetree.org/meta-schemas/core.yaml#
-+
-+title: block storage device
-+
-+description: |
-+  This binding is generic and describes a block-oriented storage device.
-+
-+maintainers:
-+  - Daniel Golle <[email protected]>
-+
-+properties:
-+  partitions:
-+    $ref: /schemas/block/partitions.yaml
-+
-+  nvmem-layout:
-+    $ref: /schemas/nvmem/layouts/nvmem-layout.yaml#
-+
-+unevaluatedProperties: false
---- /dev/null
-+++ b/Documentation/devicetree/bindings/block/partition.yaml
-@@ -0,0 +1,51 @@
-+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
-+%YAML 1.2
-+---
-+$id: http://devicetree.org/schemas/block/partition.yaml#
-+$schema: http://devicetree.org/meta-schemas/core.yaml#
-+
-+title: Partition on a block device
-+
-+description: |
-+  This binding describes a partition on a block device.
-+  Partitions may be matched by a combination of partition number, name,
-+  and UUID.
-+
-+maintainers:
-+  - Daniel Golle <[email protected]>
-+
-+properties:
-+  $nodename:
-+    pattern: '^block-partition-.+$'
-+
-+  partnum:
-+    $ref: /schemas/types.yaml#/definitions/uint32
-+    description:
-+      Matches partition by number if present.
-+
-+  partname:
-+    $ref: /schemas/types.yaml#/definitions/string
-+    description:
-+      Matches partition by PARTNAME if present.
-+
-+  partuuid:
-+    $ref: /schemas/types.yaml#/definitions/string
-+    description:
-+      Matches partition by PARTUUID if present.
-+
-+  nvmem-layout:
-+    $ref: /schemas/nvmem/layouts/nvmem-layout.yaml#
-+    description:
-+      This container may reference an NVMEM layout parser.
-+
-+anyOf:
-+  - required:
-+      - partnum
-+
-+  - required:
-+      - partname
-+
-+  - required:
-+      - partuuid
-+
-+unevaluatedProperties: false
---- /dev/null
-+++ b/Documentation/devicetree/bindings/block/partitions.yaml
-@@ -0,0 +1,20 @@
-+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
-+%YAML 1.2
-+---
-+$id: http://devicetree.org/schemas/block/partitions.yaml#
-+$schema: http://devicetree.org/meta-schemas/core.yaml#
-+
-+title: Partitions on block devices
-+
-+description: |
-+  This binding is generic and describes the content of the partitions container
-+  node.
-+
-+maintainers:
-+  - Daniel Golle <[email protected]>
-+
-+patternProperties:
-+  "^block-partition-.+$":
-+    $ref: partition.yaml
-+
-+unevaluatedProperties: false
diff --git a/target/linux/generic/pending-6.12/451-block-partitions-of-assign-Device-Tree-node-to-parti.patch b/target/linux/generic/pending-6.12/451-block-partitions-of-assign-Device-Tree-node-to-parti.patch
new file mode 100644 (file)
index 0000000..f9e41d0
--- /dev/null
@@ -0,0 +1,25 @@
+From 5d265996597a6b0d654bbeda1bc3bae197061de7 Mon Sep 17 00:00:00 2001
+From: Daniel Golle <[email protected]>
+Date: Mon, 7 Oct 2024 23:43:32 +0100
+Subject: [PATCH 2/8] block: partitions: of: assign Device Tree node to
+ partition
+
+Assign partition of_node so other drivers are able to identify a
+partition by its Device Tree node.
+
+Signed-off-by: Daniel Golle <[email protected]>
+---
+ block/partitions/of.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/block/partitions/of.c
++++ b/block/partitions/of.c
+@@ -48,7 +48,7 @@ static void add_of_partition(struct pars
+       u64 offset = of_read_number(reg, a_cells) / SECTOR_SIZE;
+       u64 size = of_read_number(reg + a_cells, s_cells) / SECTOR_SIZE;
+-      put_partition(state, slot, offset, size);
++      of_put_partition(state, slot, offset, size, np);
+       if (of_property_read_bool(np, "read-only"))
+               state->parts[slot].flags |= ADDPART_FLAG_READONLY;
diff --git a/target/linux/generic/pending-6.12/451-block-partitions-populate-fwnode.patch b/target/linux/generic/pending-6.12/451-block-partitions-populate-fwnode.patch
deleted file mode 100644 (file)
index 98c5de0..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-From patchwork Tue Jul 30 19:25:59 2024
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-X-Patchwork-Submitter: Daniel Golle <[email protected]>
-X-Patchwork-Id: 13747816
-Date: Tue, 30 Jul 2024 20:25:59 +0100
-From: Daniel Golle <[email protected]>
-To: Rob Herring <[email protected]>, Krzysztof Kozlowski <[email protected]>,
- Conor Dooley <[email protected]>, Jens Axboe <[email protected]>,
- Daniel Golle <[email protected]>, Christian Brauner <[email protected]>,
- Al Viro <[email protected]>, Li Lingfeng <[email protected]>,
- Ming Lei <[email protected]>, Christian Heusel <[email protected]>,
-       =?utf-8?b?UmFmYcWCIE1pxYJlY2tp?= <[email protected]>,
- Felix Fietkau <[email protected]>, John Crispin <[email protected]>,
- Chad Monroe <[email protected]>, Yangyu Chen <[email protected]>,
- Tianling Shen <[email protected]>, Chuanhong Guo <[email protected]>,
- Chen Minqiang <[email protected]>, [email protected],
-Subject: [PATCH v5 2/4] block: partitions: populate fwnode
-Message-ID: 
- <3051ac090ad3b3e2f5adb6b67c923261ead729a5.1722365899.git.daniel@makrotopia.org>
-References: <[email protected]>
-Precedence: bulk
-X-Mailing-List: [email protected]
-List-Id: <linux-block.vger.kernel.org>
-List-Subscribe: <mailto:[email protected]>
-List-Unsubscribe: <mailto:[email protected]>
-MIME-Version: 1.0
-Content-Disposition: inline
-In-Reply-To: <[email protected]>
-
-Assign matching firmware nodes to block partitions in order to allow
-them to be referenced e.g. as NVMEM providers.
-
-Signed-off-by: Daniel Golle <[email protected]>
----
- block/partitions/core.c | 72 +++++++++++++++++++++++++++++++++++++++++
- 1 file changed, 72 insertions(+)
-
---- a/block/partitions/core.c
-+++ b/block/partitions/core.c
-@@ -10,6 +10,8 @@
- #include <linux/ctype.h>
- #include <linux/vmalloc.h>
- #include <linux/raid/detect.h>
-+#include <linux/property.h>
-+
- #include "check.h"
- static int (*const check_part[])(struct parsed_partitions *) = {
-@@ -284,6 +286,74 @@ static ssize_t whole_disk_show(struct de
- }
- static const DEVICE_ATTR(whole_disk, 0444, whole_disk_show, NULL);
-+static bool part_meta_match(const char *attr, const char *member, size_t length)
-+{
-+      /* check if length of attr exceeds specified maximum length */
-+      if (strnlen(attr, length) == length)
-+              return false;
-+
-+      /* return true if strings match */
-+      return !strncmp(attr, member, length);
-+}
-+
-+static struct fwnode_handle *find_partition_fwnode(struct block_device *bdev)
-+{
-+      struct fwnode_handle *fw_parts, *fw_part;
-+      struct device *ddev = disk_to_dev(bdev->bd_disk);
-+      const char *partname, *uuid;
-+      u32 partno;
-+      bool got_uuid, got_partname, got_partno;
-+
-+      fw_parts = device_get_named_child_node(ddev, "partitions");
-+      if (!fw_parts)
-+              return NULL;
-+
-+      fwnode_for_each_child_node(fw_parts, fw_part) {
-+              got_uuid = false;
-+              got_partname = false;
-+              got_partno = false;
-+              /*
-+               * In case 'uuid' is defined in the partitions firmware node
-+               * require partition meta info being present and the specified
-+               * uuid to match.
-+               */
-+              got_uuid = !fwnode_property_read_string(fw_part, "uuid", &uuid);
-+              if (got_uuid && (!bdev->bd_meta_info ||
-+                               !part_meta_match(uuid, bdev->bd_meta_info->uuid,
-+                                                PARTITION_META_INFO_UUIDLTH)))
-+                      continue;
-+
-+              /*
-+               * In case 'partname' is defined in the partitions firmware node
-+               * require partition meta info being present and the specified
-+               * volname to match.
-+               */
-+              got_partname = !fwnode_property_read_string(fw_part, "partname",
-+                                                          &partname);
-+              if (got_partname && (!bdev->bd_meta_info ||
-+                                   !part_meta_match(partname,
-+                                                    bdev->bd_meta_info->volname,
-+                                                    PARTITION_META_INFO_VOLNAMELTH)))
-+                      continue;
-+
-+              /*
-+               * In case 'partno' is defined in the partitions firmware node
-+               * the specified partno needs to match.
-+               */
-+              got_partno = !fwnode_property_read_u32(fw_part, "partno", &partno);
-+              if (got_partno && bdev_partno(bdev) != partno)
-+                      continue;
-+
-+              /* Skip if no matching criteria is present in firmware node */
-+              if (!got_uuid && !got_partname && !got_partno)
-+                      continue;
-+
-+              return fw_part;
-+      }
-+
-+      return NULL;
-+}
-+
- /*
-  * Must be called either with open_mutex held, before a disk can be opened or
-  * after all disk users are gone.
-@@ -358,6 +428,8 @@ static struct block_device *add_partitio
-                       goto out_put;
-       }
-+      device_set_node(pdev, find_partition_fwnode(bdev));
-+
-       /* delay uevent until 'holders' subdir is created */
-       dev_set_uevent_suppress(pdev, 1);
-       err = device_add(pdev);
diff --git a/target/linux/generic/pending-6.12/452-block-add-support-for-notifications.patch b/target/linux/generic/pending-6.12/452-block-add-support-for-notifications.patch
deleted file mode 100644 (file)
index aed497c..0000000
+++ /dev/null
@@ -1,174 +0,0 @@
-From patchwork Tue Jul 30 19:26:42 2024
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-X-Patchwork-Submitter: Daniel Golle <[email protected]>
-X-Patchwork-Id: 13747817
-Date: Tue, 30 Jul 2024 20:26:42 +0100
-From: Daniel Golle <[email protected]>
-To: Rob Herring <[email protected]>, Krzysztof Kozlowski <[email protected]>,
- Conor Dooley <[email protected]>, Jens Axboe <[email protected]>,
- Daniel Golle <[email protected]>, Christian Brauner <[email protected]>,
- Al Viro <[email protected]>, Li Lingfeng <[email protected]>,
- Ming Lei <[email protected]>, Christian Heusel <[email protected]>,
-       =?utf-8?b?UmFmYcWCIE1pxYJlY2tp?= <[email protected]>,
- Felix Fietkau <[email protected]>, John Crispin <[email protected]>,
- Chad Monroe <[email protected]>, Yangyu Chen <[email protected]>,
- Tianling Shen <[email protected]>, Chuanhong Guo <[email protected]>,
- Chen Minqiang <[email protected]>, [email protected],
-Subject: [PATCH v5 3/4] block: add support for notifications
-Message-ID: 
- <ca0022886e8f211a323a716653a1396a3bc91653.1722365899.git.daniel@makrotopia.org>
-References: <[email protected]>
-Precedence: bulk
-X-Mailing-List: [email protected]
-List-Id: <linux-block.vger.kernel.org>
-List-Subscribe: <mailto:[email protected]>
-List-Unsubscribe: <mailto:[email protected]>
-MIME-Version: 1.0
-Content-Disposition: inline
-In-Reply-To: <[email protected]>
-
-Add notifier block to notify other subsystems about the addition or
-removal of block devices.
-
-Signed-off-by: Daniel Golle <[email protected]>
----
- block/Kconfig          |  6 +++
- block/Makefile         |  1 +
- block/blk-notify.c     | 87 ++++++++++++++++++++++++++++++++++++++++++
- include/linux/blkdev.h | 11 ++++++
- 4 files changed, 105 insertions(+)
- create mode 100644 block/blk-notify.c
-
---- a/block/Kconfig
-+++ b/block/Kconfig
-@@ -209,6 +209,12 @@ config BLK_INLINE_ENCRYPTION_FALLBACK
-         by falling back to the kernel crypto API when inline
-         encryption hardware is not present.
-+config BLOCK_NOTIFIERS
-+      bool "Enable support for notifications in block layer"
-+      help
-+        Enable this option to provide notifiers for other subsystems
-+        upon addition or removal of block devices.
-+
- source "block/partitions/Kconfig"
- config BLK_MQ_PCI
---- a/block/Makefile
-+++ b/block/Makefile
-@@ -38,3 +38,4 @@ obj-$(CONFIG_BLK_INLINE_ENCRYPTION)  += b
-                                          blk-crypto-sysfs.o
- obj-$(CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK)  += blk-crypto-fallback.o
- obj-$(CONFIG_BLOCK_HOLDER_DEPRECATED) += holder.o
-+obj-$(CONFIG_BLOCK_NOTIFIERS) += blk-notify.o
---- /dev/null
-+++ b/block/blk-notify.c
-@@ -0,0 +1,87 @@
-+// SPDX-License-Identifier: GPL-2.0-or-later
-+/*
-+ * Notifiers for addition and removal of block devices
-+ *
-+ * Copyright (c) 2024 Daniel Golle <[email protected]>
-+ */
-+
-+#include <linux/list.h>
-+#include <linux/mutex.h>
-+#include <linux/notifier.h>
-+
-+#include "blk.h"
-+
-+struct blk_device_list {
-+      struct device *dev;
-+      struct list_head list;
-+};
-+
-+static RAW_NOTIFIER_HEAD(blk_notifier_list);
-+static DEFINE_MUTEX(blk_notifier_lock);
-+static LIST_HEAD(blk_devices);
-+
-+void blk_register_notify(struct notifier_block *nb)
-+{
-+      struct blk_device_list *existing_blkdev;
-+
-+      mutex_lock(&blk_notifier_lock);
-+      raw_notifier_chain_register(&blk_notifier_list, nb);
-+
-+      list_for_each_entry(existing_blkdev, &blk_devices, list)
-+              nb->notifier_call(nb, BLK_DEVICE_ADD, existing_blkdev->dev);
-+
-+      mutex_unlock(&blk_notifier_lock);
-+}
-+EXPORT_SYMBOL_GPL(blk_register_notify);
-+
-+void blk_unregister_notify(struct notifier_block *nb)
-+{
-+      mutex_lock(&blk_notifier_lock);
-+      raw_notifier_chain_unregister(&blk_notifier_list, nb);
-+      mutex_unlock(&blk_notifier_lock);
-+}
-+EXPORT_SYMBOL_GPL(blk_unregister_notify);
-+
-+static int blk_call_notifier_add(struct device *dev)
-+{
-+      struct blk_device_list *new_blkdev;
-+
-+      new_blkdev = kmalloc(sizeof(*new_blkdev), GFP_KERNEL);
-+      if (!new_blkdev)
-+              return -ENOMEM;
-+
-+      new_blkdev->dev = dev;
-+      mutex_lock(&blk_notifier_lock);
-+      list_add_tail(&new_blkdev->list, &blk_devices);
-+      raw_notifier_call_chain(&blk_notifier_list, BLK_DEVICE_ADD, dev);
-+      mutex_unlock(&blk_notifier_lock);
-+      return 0;
-+}
-+
-+static void blk_call_notifier_remove(struct device *dev)
-+{
-+      struct blk_device_list *old_blkdev, *tmp;
-+
-+      mutex_lock(&blk_notifier_lock);
-+      list_for_each_entry_safe(old_blkdev, tmp, &blk_devices, list) {
-+              if (old_blkdev->dev != dev)
-+                      continue;
-+
-+              list_del(&old_blkdev->list);
-+              kfree(old_blkdev);
-+      }
-+      raw_notifier_call_chain(&blk_notifier_list, BLK_DEVICE_REMOVE, dev);
-+      mutex_unlock(&blk_notifier_lock);
-+}
-+
-+static struct class_interface blk_notifications_bus_interface __refdata = {
-+      .class = &block_class,
-+      .add_dev = &blk_call_notifier_add,
-+      .remove_dev = &blk_call_notifier_remove,
-+};
-+
-+static int __init blk_notifications_init(void)
-+{
-+      return class_interface_register(&blk_notifications_bus_interface);
-+}
-+device_initcall(blk_notifications_init);
---- a/include/linux/blkdev.h
-+++ b/include/linux/blkdev.h
-@@ -1696,4 +1696,15 @@ static inline bool bdev_can_atomic_write
- #define DEFINE_IO_COMP_BATCH(name)    struct io_comp_batch name = { }
-+
-+#define BLK_DEVICE_ADD                1
-+#define BLK_DEVICE_REMOVE     2
-+#if defined(CONFIG_BLOCK_NOTIFIERS)
-+void blk_register_notify(struct notifier_block *nb);
-+void blk_unregister_notify(struct notifier_block *nb);
-+#else
-+static inline void blk_register_notify(struct notifier_block *nb) { };
-+static inline void blk_unregister_notify(struct notifier_block *nb) { };
-+#endif
-+
- #endif /* _LINUX_BLKDEV_H */
diff --git a/target/linux/generic/pending-6.12/452-partitions-efi-apply-Linux-code-style.patch b/target/linux/generic/pending-6.12/452-partitions-efi-apply-Linux-code-style.patch
new file mode 100644 (file)
index 0000000..6e996ca
--- /dev/null
@@ -0,0 +1,498 @@
+From d4e82837c8b86ff2c21fa923271908988bc72faa Mon Sep 17 00:00:00 2001
+From: Daniel Golle <[email protected]>
+Date: Mon, 7 Oct 2024 23:22:53 +0100
+Subject: [PATCH 3/8] partitions/efi: apply Linux code style
+
+Fix (mostly white space related) coding style issues in
+block/partitions/efi.c by use of clang-format.
+
+Signed-off-by: Daniel Golle <[email protected]>
+---
+ block/partitions/efi.c | 235 +++++++++++++++++++++--------------------
+ 1 file changed, 121 insertions(+), 114 deletions(-)
+
+--- a/block/partitions/efi.c
++++ b/block/partitions/efi.c
+@@ -95,15 +95,13 @@
+  * the partition tables happens after init too.
+  */
+ static int force_gpt;
+-static int __init
+-force_gpt_fn(char *str)
++static int __init force_gpt_fn(char *str)
+ {
+       force_gpt = 1;
+       return 1;
+ }
+ __setup("gpt", force_gpt_fn);
+-
+ /**
+  * efi_crc32() - EFI version of crc32 function
+  * @buf: buffer to calculate crc32 of
+@@ -116,8 +114,7 @@ __setup("gpt", force_gpt_fn);
+  * Note, the EFI Specification, v1.02, has a reference to
+  * Dr. Dobbs Journal, May 1994 (actually it's in May 1992).
+  */
+-static inline u32
+-efi_crc32(const void *buf, unsigned long len)
++static inline u32 efi_crc32(const void *buf, unsigned long len)
+ {
+       return (crc32(~0L, buf, len) ^ ~0L);
+ }
+@@ -134,7 +131,8 @@ efi_crc32(const void *buf, unsigned long
+ static u64 last_lba(struct gendisk *disk)
+ {
+       return div_u64(bdev_nr_bytes(disk->part0),
+-                     queue_logical_block_size(disk->queue)) - 1ULL;
++                     queue_logical_block_size(disk->queue)) -
++             1ULL;
+ }
+ static inline int pmbr_part_valid(gpt_mbr_record *part)
+@@ -195,7 +193,7 @@ static int is_pmbr_valid(legacy_mbr *mbr
+ check_hybrid:
+       for (i = 0; i < 4; i++)
+               if ((mbr->partition_record[i].os_type !=
+-                      EFI_PMBR_OSTYPE_EFI_GPT) &&
++                   EFI_PMBR_OSTYPE_EFI_GPT) &&
+                   (mbr->partition_record[i].os_type != 0x00))
+                       ret = GPT_MBR_HYBRID;
+@@ -213,10 +211,11 @@ check_hybrid:
+        */
+       if (ret == GPT_MBR_PROTECTIVE) {
+               sz = le32_to_cpu(mbr->partition_record[part].size_in_lba);
+-              if (sz != (uint32_t) total_sectors - 1 && sz != 0xFFFFFFFF)
+-                      pr_debug("GPT: mbr size in lba (%u) different than whole disk (%u).\n",
+-                               sz, min_t(uint32_t,
+-                                         total_sectors - 1, 0xFFFFFFFF));
++              if (sz != (uint32_t)total_sectors - 1 && sz != 0xFFFFFFFF)
++                      pr_debug(
++                              "GPT: mbr size in lba (%u) different than whole disk (%u).\n",
++                              sz,
++                              min_t(uint32_t, total_sectors - 1, 0xFFFFFFFF));
+       }
+ done:
+       return ret;
+@@ -232,15 +231,14 @@ done:
+  * Description: Reads @count bytes from @state->disk into @buffer.
+  * Returns number of bytes read on success, 0 on error.
+  */
+-static size_t read_lba(struct parsed_partitions *state,
+-                     u64 lba, u8 *buffer, size_t count)
++static size_t read_lba(struct parsed_partitions *state, u64 lba, u8 *buffer,
++                     size_t count)
+ {
+       size_t totalreadcount = 0;
+-      sector_t n = lba *
+-              (queue_logical_block_size(state->disk->queue) / 512);
++      sector_t n = lba * (queue_logical_block_size(state->disk->queue) / 512);
+       if (!buffer || lba > last_lba(state->disk))
+-                return 0;
++              return 0;
+       while (count) {
+               int copied = 512;
+@@ -253,7 +251,7 @@ static size_t read_lba(struct parsed_par
+               memcpy(buffer, data, copied);
+               put_dev_sector(sect);
+               buffer += copied;
+-              totalreadcount +=copied;
++              totalreadcount += copied;
+               count -= copied;
+       }
+       return totalreadcount;
+@@ -278,17 +276,17 @@ static gpt_entry *alloc_read_gpt_entries
+               return NULL;
+       count = (size_t)le32_to_cpu(gpt->num_partition_entries) *
+-                le32_to_cpu(gpt->sizeof_partition_entry);
++              le32_to_cpu(gpt->sizeof_partition_entry);
+       if (!count)
+               return NULL;
+       pte = kmalloc(count, GFP_KERNEL);
+       if (!pte)
+               return NULL;
+-      if (read_lba(state, le64_to_cpu(gpt->partition_entry_lba),
+-                      (u8 *) pte, count) < count) {
++      if (read_lba(state, le64_to_cpu(gpt->partition_entry_lba), (u8 *)pte,
++                   count) < count) {
+               kfree(pte);
+-                pte=NULL;
++              pte = NULL;
+               return NULL;
+       }
+       return pte;
+@@ -313,9 +311,9 @@ static gpt_header *alloc_read_gpt_header
+       if (!gpt)
+               return NULL;
+-      if (read_lba(state, lba, (u8 *) gpt, ssz) < ssz) {
++      if (read_lba(state, lba, (u8 *)gpt, ssz) < ssz) {
+               kfree(gpt);
+-                gpt=NULL;
++              gpt = NULL;
+               return NULL;
+       }
+@@ -354,8 +352,9 @@ static int is_gpt_valid(struct parsed_pa
+       /* Check the GUID Partition Table header size is too big */
+       if (le32_to_cpu((*gpt)->header_size) >
+-                      queue_logical_block_size(state->disk->queue)) {
+-              pr_debug("GUID Partition Table Header size is too large: %u > %u\n",
++          queue_logical_block_size(state->disk->queue)) {
++              pr_debug(
++                      "GUID Partition Table Header size is too large: %u > %u\n",
+                       le32_to_cpu((*gpt)->header_size),
+                       queue_logical_block_size(state->disk->queue));
+               goto fail;
+@@ -363,16 +362,17 @@ static int is_gpt_valid(struct parsed_pa
+       /* Check the GUID Partition Table header size is too small */
+       if (le32_to_cpu((*gpt)->header_size) < sizeof(gpt_header)) {
+-              pr_debug("GUID Partition Table Header size is too small: %u < %zu\n",
+-                      le32_to_cpu((*gpt)->header_size),
+-                      sizeof(gpt_header));
++              pr_debug(
++                      "GUID Partition Table Header size is too small: %u < %zu\n",
++                      le32_to_cpu((*gpt)->header_size), sizeof(gpt_header));
+               goto fail;
+       }
+       /* Check the GUID Partition Table CRC */
+       origcrc = le32_to_cpu((*gpt)->header_crc32);
+       (*gpt)->header_crc32 = 0;
+-      crc = efi_crc32((const unsigned char *) (*gpt), le32_to_cpu((*gpt)->header_size));
++      crc = efi_crc32((const unsigned char *)(*gpt),
++                      le32_to_cpu((*gpt)->header_size));
+       if (crc != origcrc) {
+               pr_debug("GUID Partition Table Header CRC is wrong: %x != %x\n",
+@@ -396,20 +396,25 @@ static int is_gpt_valid(struct parsed_pa
+       lastlba = last_lba(state->disk);
+       if (le64_to_cpu((*gpt)->first_usable_lba) > lastlba) {
+               pr_debug("GPT: first_usable_lba incorrect: %lld > %lld\n",
+-                       (unsigned long long)le64_to_cpu((*gpt)->first_usable_lba),
++                       (unsigned long long)le64_to_cpu(
++                               (*gpt)->first_usable_lba),
+                        (unsigned long long)lastlba);
+               goto fail;
+       }
+       if (le64_to_cpu((*gpt)->last_usable_lba) > lastlba) {
+               pr_debug("GPT: last_usable_lba incorrect: %lld > %lld\n",
+-                       (unsigned long long)le64_to_cpu((*gpt)->last_usable_lba),
++                       (unsigned long long)le64_to_cpu(
++                               (*gpt)->last_usable_lba),
+                        (unsigned long long)lastlba);
+               goto fail;
+       }
+-      if (le64_to_cpu((*gpt)->last_usable_lba) < le64_to_cpu((*gpt)->first_usable_lba)) {
++      if (le64_to_cpu((*gpt)->last_usable_lba) <
++          le64_to_cpu((*gpt)->first_usable_lba)) {
+               pr_debug("GPT: last_usable_lba incorrect: %lld > %lld\n",
+-                       (unsigned long long)le64_to_cpu((*gpt)->last_usable_lba),
+-                       (unsigned long long)le64_to_cpu((*gpt)->first_usable_lba));
++                       (unsigned long long)le64_to_cpu(
++                               (*gpt)->last_usable_lba),
++                       (unsigned long long)le64_to_cpu(
++                               (*gpt)->first_usable_lba));
+               goto fail;
+       }
+       /* Check that sizeof_partition_entry has the correct value */
+@@ -420,10 +425,11 @@ static int is_gpt_valid(struct parsed_pa
+       /* Sanity check partition table size */
+       pt_size = (u64)le32_to_cpu((*gpt)->num_partition_entries) *
+-              le32_to_cpu((*gpt)->sizeof_partition_entry);
++                le32_to_cpu((*gpt)->sizeof_partition_entry);
+       if (pt_size > KMALLOC_MAX_SIZE) {
+-              pr_debug("GUID Partition Table is too large: %llu > %lu bytes\n",
+-                       (unsigned long long)pt_size, KMALLOC_MAX_SIZE);
++              pr_debug(
++                      "GUID Partition Table is too large: %llu > %lu bytes\n",
++                      (unsigned long long)pt_size, KMALLOC_MAX_SIZE);
+               goto fail;
+       }
+@@ -431,7 +437,7 @@ static int is_gpt_valid(struct parsed_pa
+               goto fail;
+       /* Check the GUID Partition Entry Array CRC */
+-      crc = efi_crc32((const unsigned char *) (*ptes), pt_size);
++      crc = efi_crc32((const unsigned char *)(*ptes), pt_size);
+       if (crc != le32_to_cpu((*gpt)->partition_entry_array_crc32)) {
+               pr_debug("GUID Partition Entry Array CRC check failed.\n");
+@@ -441,10 +447,10 @@ static int is_gpt_valid(struct parsed_pa
+       /* We're done, all's well */
+       return 1;
+- fail_ptes:
++fail_ptes:
+       kfree(*ptes);
+       *ptes = NULL;
+- fail:
++fail:
+       kfree(*gpt);
+       *gpt = NULL;
+       return 0;
+@@ -457,12 +463,11 @@ static int is_gpt_valid(struct parsed_pa
+  *
+  * Description: returns 1 if valid,  0 on error.
+  */
+-static inline int
+-is_pte_valid(const gpt_entry *pte, const u64 lastlba)
++static inline int is_pte_valid(const gpt_entry *pte, const u64 lastlba)
+ {
+       if ((!efi_guidcmp(pte->partition_type_guid, NULL_GUID)) ||
+-          le64_to_cpu(pte->starting_lba) > lastlba         ||
+-          le64_to_cpu(pte->ending_lba)   > lastlba)
++          le64_to_cpu(pte->starting_lba) > lastlba ||
++          le64_to_cpu(pte->ending_lba) > lastlba)
+               return 0;
+       return 1;
+ }
+@@ -477,8 +482,7 @@ is_pte_valid(const gpt_entry *pte, const
+  * and prints warnings on discrepancies.
+  * 
+  */
+-static void
+-compare_gpts(gpt_header *pgpt, gpt_header *agpt, u64 lastlba)
++static void compare_gpts(gpt_header *pgpt, gpt_header *agpt, u64 lastlba)
+ {
+       int error_found = 0;
+       if (!pgpt || !agpt)
+@@ -486,31 +490,32 @@ compare_gpts(gpt_header *pgpt, gpt_heade
+       if (le64_to_cpu(pgpt->my_lba) != le64_to_cpu(agpt->alternate_lba)) {
+               pr_warn("GPT:Primary header LBA != Alt. header alternate_lba\n");
+               pr_warn("GPT:%lld != %lld\n",
+-                     (unsigned long long)le64_to_cpu(pgpt->my_lba),
+-                       (unsigned long long)le64_to_cpu(agpt->alternate_lba));
++                      (unsigned long long)le64_to_cpu(pgpt->my_lba),
++                      (unsigned long long)le64_to_cpu(agpt->alternate_lba));
+               error_found++;
+       }
+       if (le64_to_cpu(pgpt->alternate_lba) != le64_to_cpu(agpt->my_lba)) {
+               pr_warn("GPT:Primary header alternate_lba != Alt. header my_lba\n");
+               pr_warn("GPT:%lld != %lld\n",
+-                     (unsigned long long)le64_to_cpu(pgpt->alternate_lba),
+-                       (unsigned long long)le64_to_cpu(agpt->my_lba));
++                      (unsigned long long)le64_to_cpu(pgpt->alternate_lba),
++                      (unsigned long long)le64_to_cpu(agpt->my_lba));
+               error_found++;
+       }
+       if (le64_to_cpu(pgpt->first_usable_lba) !=
+-            le64_to_cpu(agpt->first_usable_lba)) {
++          le64_to_cpu(agpt->first_usable_lba)) {
+               pr_warn("GPT:first_usable_lbas don't match.\n");
+               pr_warn("GPT:%lld != %lld\n",
+-                     (unsigned long long)le64_to_cpu(pgpt->first_usable_lba),
+-                       (unsigned long long)le64_to_cpu(agpt->first_usable_lba));
++                      (unsigned long long)le64_to_cpu(pgpt->first_usable_lba),
++                      (unsigned long long)le64_to_cpu(
++                              agpt->first_usable_lba));
+               error_found++;
+       }
+       if (le64_to_cpu(pgpt->last_usable_lba) !=
+-            le64_to_cpu(agpt->last_usable_lba)) {
++          le64_to_cpu(agpt->last_usable_lba)) {
+               pr_warn("GPT:last_usable_lbas don't match.\n");
+               pr_warn("GPT:%lld != %lld\n",
+-                     (unsigned long long)le64_to_cpu(pgpt->last_usable_lba),
+-                       (unsigned long long)le64_to_cpu(agpt->last_usable_lba));
++                      (unsigned long long)le64_to_cpu(pgpt->last_usable_lba),
++                      (unsigned long long)le64_to_cpu(agpt->last_usable_lba));
+               error_found++;
+       }
+       if (efi_guidcmp(pgpt->disk_guid, agpt->disk_guid)) {
+@@ -518,27 +523,27 @@ compare_gpts(gpt_header *pgpt, gpt_heade
+               error_found++;
+       }
+       if (le32_to_cpu(pgpt->num_partition_entries) !=
+-            le32_to_cpu(agpt->num_partition_entries)) {
++          le32_to_cpu(agpt->num_partition_entries)) {
+               pr_warn("GPT:num_partition_entries don't match: "
+-                     "0x%x != 0x%x\n",
+-                     le32_to_cpu(pgpt->num_partition_entries),
+-                     le32_to_cpu(agpt->num_partition_entries));
++                      "0x%x != 0x%x\n",
++                      le32_to_cpu(pgpt->num_partition_entries),
++                      le32_to_cpu(agpt->num_partition_entries));
+               error_found++;
+       }
+       if (le32_to_cpu(pgpt->sizeof_partition_entry) !=
+-            le32_to_cpu(agpt->sizeof_partition_entry)) {
++          le32_to_cpu(agpt->sizeof_partition_entry)) {
+               pr_warn("GPT:sizeof_partition_entry values don't match: "
+-                     "0x%x != 0x%x\n",
+-                       le32_to_cpu(pgpt->sizeof_partition_entry),
+-                     le32_to_cpu(agpt->sizeof_partition_entry));
++                      "0x%x != 0x%x\n",
++                      le32_to_cpu(pgpt->sizeof_partition_entry),
++                      le32_to_cpu(agpt->sizeof_partition_entry));
+               error_found++;
+       }
+       if (le32_to_cpu(pgpt->partition_entry_array_crc32) !=
+-            le32_to_cpu(agpt->partition_entry_array_crc32)) {
++          le32_to_cpu(agpt->partition_entry_array_crc32)) {
+               pr_warn("GPT:partition_entry_array_crc32 values don't match: "
+-                     "0x%x != 0x%x\n",
+-                       le32_to_cpu(pgpt->partition_entry_array_crc32),
+-                     le32_to_cpu(agpt->partition_entry_array_crc32));
++                      "0x%x != 0x%x\n",
++                      le32_to_cpu(pgpt->partition_entry_array_crc32),
++                      le32_to_cpu(agpt->partition_entry_array_crc32));
+               error_found++;
+       }
+       if (le64_to_cpu(pgpt->alternate_lba) != lastlba) {
+@@ -594,7 +599,7 @@ static int find_valid_gpt(struct parsed_
+               return 0;
+       lastlba = last_lba(state->disk);
+-        if (!force_gpt) {
++      if (!force_gpt) {
+               /* This will be added to the EFI Spec. per Intel after v1.02. */
+               legacymbr = kzalloc(sizeof(*legacymbr), GFP_KERNEL);
+               if (!legacymbr)
+@@ -608,18 +613,17 @@ static int find_valid_gpt(struct parsed_
+                       goto fail;
+               pr_debug("Device has a %s MBR\n",
+-                       good_pmbr == GPT_MBR_PROTECTIVE ?
+-                                              "protective" : "hybrid");
++                       good_pmbr == GPT_MBR_PROTECTIVE ? "protective" :
++                                                         "hybrid");
+       }
+-      good_pgpt = is_gpt_valid(state, GPT_PRIMARY_PARTITION_TABLE_LBA,
+-                               &pgpt, &pptes);
+-        if (good_pgpt)
+-              good_agpt = is_gpt_valid(state,
+-                                       le64_to_cpu(pgpt->alternate_lba),
+-                                       &agpt, &aptes);
+-        if (!good_agpt && force_gpt)
+-                good_agpt = is_gpt_valid(state, lastlba, &agpt, &aptes);
++      good_pgpt = is_gpt_valid(state, GPT_PRIMARY_PARTITION_TABLE_LBA, &pgpt,
++                               &pptes);
++      if (good_pgpt)
++              good_agpt = is_gpt_valid(
++                      state, le64_to_cpu(pgpt->alternate_lba), &agpt, &aptes);
++      if (!good_agpt && force_gpt)
++              good_agpt = is_gpt_valid(state, lastlba, &agpt, &aptes);
+       if (!good_agpt && force_gpt && fops->alternative_gpt_sector) {
+               sector_t agpt_sector;
+@@ -627,43 +631,42 @@ static int find_valid_gpt(struct parsed_
+               err = fops->alternative_gpt_sector(disk, &agpt_sector);
+               if (!err)
+-                      good_agpt = is_gpt_valid(state, agpt_sector,
+-                                               &agpt, &aptes);
++                      good_agpt =
++                              is_gpt_valid(state, agpt_sector, &agpt, &aptes);
+       }
+-        /* The obviously unsuccessful case */
+-        if (!good_pgpt && !good_agpt)
+-                goto fail;
+-
+-        compare_gpts(pgpt, agpt, lastlba);
+-
+-        /* The good cases */
+-        if (good_pgpt) {
+-                *gpt  = pgpt;
+-                *ptes = pptes;
+-                kfree(agpt);
+-                kfree(aptes);
++      /* The obviously unsuccessful case */
++      if (!good_pgpt && !good_agpt)
++              goto fail;
++
++      compare_gpts(pgpt, agpt, lastlba);
++
++      /* The good cases */
++      if (good_pgpt) {
++              *gpt = pgpt;
++              *ptes = pptes;
++              kfree(agpt);
++              kfree(aptes);
+               if (!good_agpt)
+-                        pr_warn("Alternate GPT is invalid, using primary GPT.\n");
+-                return 1;
+-        }
+-        else if (good_agpt) {
+-                *gpt  = agpt;
+-                *ptes = aptes;
+-                kfree(pgpt);
+-                kfree(pptes);
++                      pr_warn("Alternate GPT is invalid, using primary GPT.\n");
++              return 1;
++      } else if (good_agpt) {
++              *gpt = agpt;
++              *ptes = aptes;
++              kfree(pgpt);
++              kfree(pptes);
+               pr_warn("Primary GPT is invalid, using alternate GPT.\n");
+-                return 1;
+-        }
++              return 1;
++      }
+- fail:
+-        kfree(pgpt);
+-        kfree(agpt);
+-        kfree(pptes);
+-        kfree(aptes);
+-        *gpt = NULL;
+-        *ptes = NULL;
+-        return 0;
++fail:
++      kfree(pgpt);
++      kfree(agpt);
++      kfree(pptes);
++      kfree(aptes);
++      *gpt = NULL;
++      *ptes = NULL;
++      return 0;
+ }
+ /**
+@@ -725,7 +728,9 @@ int efi_partition(struct parsed_partitio
+       pr_debug("GUID Partition Table is valid!  Yea!\n");
+-      for (i = 0; i < le32_to_cpu(gpt->num_partition_entries) && i < state->limit-1; i++) {
++      for (i = 0; i < le32_to_cpu(gpt->num_partition_entries) &&
++                  i < state->limit - 1;
++           i++) {
+               struct partition_meta_info *info;
+               unsigned label_max;
+               u64 start = le64_to_cpu(ptes[i].starting_lba);
+@@ -735,10 +740,11 @@ int efi_partition(struct parsed_partitio
+               if (!is_pte_valid(&ptes[i], last_lba(state->disk)))
+                       continue;
+-              put_partition(state, i+1, start * ssz, size * ssz);
++              put_partition(state, i + 1, start * ssz, size * ssz);
+               /* If this is a RAID volume, tell md */
+-              if (!efi_guidcmp(ptes[i].partition_type_guid, PARTITION_LINUX_RAID_GUID))
++              if (!efi_guidcmp(ptes[i].partition_type_guid,
++                               PARTITION_LINUX_RAID_GUID))
+                       state->parts[i + 1].flags = ADDPART_FLAG_RAID;
+               info = &state->parts[i + 1].info;
+@@ -747,7 +753,8 @@ int efi_partition(struct parsed_partitio
+               /* Naively convert UTF16-LE to 7 bits. */
+               label_max = min(ARRAY_SIZE(info->volname) - 1,
+                               ARRAY_SIZE(ptes[i].partition_name));
+-              utf16_le_to_7bit(ptes[i].partition_name, label_max, info->volname);
++              utf16_le_to_7bit(ptes[i].partition_name, label_max,
++                               info->volname);
+               state->parts[i + 1].has_info = true;
+       }
+       kfree(ptes);
diff --git a/target/linux/generic/pending-6.12/453-block-add-new-genhd-flag-GENHD_FL_NVMEM.patch b/target/linux/generic/pending-6.12/453-block-add-new-genhd-flag-GENHD_FL_NVMEM.patch
deleted file mode 100644 (file)
index 36dc9e6..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-From patchwork Tue Jul 30 19:27:07 2024
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-X-Patchwork-Submitter: Daniel Golle <[email protected]>
-X-Patchwork-Id: 13747818
-Date: Tue, 30 Jul 2024 20:27:07 +0100
-From: Daniel Golle <[email protected]>
-To: Rob Herring <[email protected]>, Krzysztof Kozlowski <[email protected]>,
- Conor Dooley <[email protected]>, Jens Axboe <[email protected]>,
- Daniel Golle <[email protected]>, Christian Brauner <[email protected]>,
- Al Viro <[email protected]>, Li Lingfeng <[email protected]>,
- Ming Lei <[email protected]>, Christian Heusel <[email protected]>,
-       =?utf-8?b?UmFmYcWCIE1pxYJlY2tp?= <[email protected]>,
- Felix Fietkau <[email protected]>, John Crispin <[email protected]>,
- Chad Monroe <[email protected]>, Yangyu Chen <[email protected]>,
- Tianling Shen <[email protected]>, Chuanhong Guo <[email protected]>,
- Chen Minqiang <[email protected]>, [email protected],
-Subject: [PATCH v5 4/4] block: add new genhd flag GENHD_FL_NVMEM
-Message-ID: 
- <311ea569c23ce14e2896cd3b069dc494c58c49c2.1722365899.git.daniel@makrotopia.org>
-References: <[email protected]>
-Precedence: bulk
-X-Mailing-List: [email protected]
-List-Id: <linux-block.vger.kernel.org>
-List-Subscribe: <mailto:[email protected]>
-List-Unsubscribe: <mailto:[email protected]>
-MIME-Version: 1.0
-Content-Disposition: inline
-In-Reply-To: <[email protected]>
-
-Add new flag to destinguish block devices which may act as an NVMEM
-provider.
-
-Signed-off-by: Daniel Golle <[email protected]>
----
- include/linux/blkdev.h | 2 ++
- 1 file changed, 2 insertions(+)
-
---- a/include/linux/blkdev.h
-+++ b/include/linux/blkdev.h
-@@ -82,11 +82,13 @@ struct partition_meta_info {
-  * ``GENHD_FL_NO_PART``: partition support is disabled.  The kernel will not
-  * scan for partitions from add_disk, and users can't add partitions manually.
-  *
-+ * ``GENHD_FL_NVMEM``: the block device should be considered as NVMEM provider.
-  */
- enum {
-       GENHD_FL_REMOVABLE                      = 1 << 0,
-       GENHD_FL_HIDDEN                         = 1 << 1,
-       GENHD_FL_NO_PART                        = 1 << 2,
-+      GENHD_FL_NVMEM                          = 1 << 3,
- };
- enum {
diff --git a/target/linux/generic/pending-6.12/453-partitions-efi-allow-assigning-partition-Device-Tree.patch b/target/linux/generic/pending-6.12/453-partitions-efi-allow-assigning-partition-Device-Tree.patch
new file mode 100644 (file)
index 0000000..cc2c203
--- /dev/null
@@ -0,0 +1,75 @@
+From f28e36c19b927671d93ccd2b5de3d518fccf721e Mon Sep 17 00:00:00 2001
+From: Daniel Golle <[email protected]>
+Date: Tue, 8 Oct 2024 00:25:12 +0100
+Subject: [PATCH 4/8] partitions/efi: allow assigning partition Device Tree
+ node
+
+Signed-off-by: Daniel Golle <[email protected]>
+---
+ block/partitions/efi.c | 34 +++++++++++++++++++++++++++++++++-
+ 1 file changed, 33 insertions(+), 1 deletion(-)
+
+--- a/block/partitions/efi.c
++++ b/block/partitions/efi.c
+@@ -86,6 +86,7 @@
+ #include <linux/crc32.h>
+ #include <linux/ctype.h>
+ #include <linux/math64.h>
++#include <linux/of.h>
+ #include <linux/slab.h>
+ #include "check.h"
+ #include "efi.h"
+@@ -694,6 +695,34 @@ static void utf16_le_to_7bit(const __le1
+       }
+ }
++static struct device_node *find_partition_of_node(struct device_node *partitions_np,
++                                                gpt_entry *ptes)
++{
++      char volname[64], partuuid[UUID_STRING_LEN + 1];
++      const char *uuid, *name;
++
++      if (!partitions_np ||
++          !of_device_is_compatible(partitions_np, "gpt-partitions"))
++              return NULL;
++
++      efi_guid_to_str(&ptes->unique_partition_guid, partuuid);
++      utf16_le_to_7bit(ptes->partition_name, ARRAY_SIZE(volname) - 1, volname);
++
++      for_each_available_child_of_node_scoped(partitions_np, np) {
++              if (!of_property_read_string(np, "uuid", &uuid) &&
++                  strncmp(uuid, partuuid, ARRAY_SIZE(partuuid)))
++                      continue;
++
++              if (!of_property_read_string(np, "partname", &name) &&
++                  strncmp(name, volname, ARRAY_SIZE(volname)))
++                      continue;
++
++              return np;
++      }
++
++      return NULL;
++}
++
+ /**
+  * efi_partition - scan for GPT partitions
+  * @state: disk parsed partitions
+@@ -719,6 +748,8 @@ int efi_partition(struct parsed_partitio
+       gpt_entry *ptes = NULL;
+       u32 i;
+       unsigned ssz = queue_logical_block_size(state->disk->queue) / 512;
++      struct device *ddev = disk_to_dev(state->disk);
++      struct device_node *partitions_np = of_node_get(ddev->of_node);
+       if (!find_valid_gpt(state, &gpt, &ptes) || !gpt || !ptes) {
+               kfree(gpt);
+@@ -740,7 +771,8 @@ int efi_partition(struct parsed_partitio
+               if (!is_pte_valid(&ptes[i], last_lba(state->disk)))
+                       continue;
+-              put_partition(state, i + 1, start * ssz, size * ssz);
++              of_put_partition(state, i + 1, start * ssz, size * ssz,
++                               find_partition_of_node(partitions_np, &ptes[i]));
+               /* If this is a RAID volume, tell md */
+               if (!efi_guidcmp(ptes[i].partition_type_guid,
diff --git a/target/linux/generic/pending-6.12/454-block-add-support-for-notifications.patch b/target/linux/generic/pending-6.12/454-block-add-support-for-notifications.patch
new file mode 100644 (file)
index 0000000..300cbf7
--- /dev/null
@@ -0,0 +1,164 @@
+From 858df9db80c1568db255659baca7602504f823af Mon Sep 17 00:00:00 2001
+From: Daniel Golle <[email protected]>
+Date: Wed, 15 May 2024 08:19:51 +0100
+Subject: [PATCH 5/8] block: add support for notifications
+
+Add notifier block to notify other subsystems about the addition or
+removal of block devices.
+
+Signed-off-by: Daniel Golle <[email protected]>
+---
+ block/Kconfig          |   6 +++
+ block/Makefile         |   1 +
+ block/blk-notify.c     | 107 +++++++++++++++++++++++++++++++++++++++++
+ include/linux/blkdev.h |   8 +++
+ 4 files changed, 122 insertions(+)
+ create mode 100644 block/blk-notify.c
+
+--- a/block/Kconfig
++++ b/block/Kconfig
+@@ -209,6 +209,12 @@ config BLK_INLINE_ENCRYPTION_FALLBACK
+         by falling back to the kernel crypto API when inline
+         encryption hardware is not present.
++config BLOCK_NOTIFIERS
++      bool "Enable support for notifications in block layer"
++      help
++        Enable this option to provide notifiers for other subsystems
++        upon addition or removal of block devices.
++
+ source "block/partitions/Kconfig"
+ config BLK_MQ_PCI
+--- a/block/Makefile
++++ b/block/Makefile
+@@ -38,3 +38,4 @@ obj-$(CONFIG_BLK_INLINE_ENCRYPTION)  += b
+                                          blk-crypto-sysfs.o
+ obj-$(CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK)  += blk-crypto-fallback.o
+ obj-$(CONFIG_BLOCK_HOLDER_DEPRECATED) += holder.o
++obj-$(CONFIG_BLOCK_NOTIFIERS) += blk-notify.o
+--- /dev/null
++++ b/block/blk-notify.c
+@@ -0,0 +1,107 @@
++// SPDX-License-Identifier: GPL-2.0-or-later
++/*
++ * Notifiers for addition and removal of block devices
++ *
++ * Copyright (c) 2024 Daniel Golle <[email protected]>
++ */
++
++#include <linux/list.h>
++#include <linux/mutex.h>
++#include <linux/notifier.h>
++#include <linux/workqueue.h>
++
++#include "blk.h"
++
++struct blk_device_list {
++      struct device *dev;
++      struct list_head list;
++};
++
++static RAW_NOTIFIER_HEAD(blk_notifier_list);
++static DEFINE_MUTEX(blk_notifier_lock);
++static LIST_HEAD(blk_devices);
++
++struct blk_notify_event {
++      struct delayed_work work;
++      struct device *dev;
++};
++
++void blk_register_notify(struct notifier_block *nb)
++{
++      struct blk_device_list *existing_blkdev;
++
++      mutex_lock(&blk_notifier_lock);
++      raw_notifier_chain_register(&blk_notifier_list, nb);
++
++      list_for_each_entry(existing_blkdev, &blk_devices, list)
++              nb->notifier_call(nb, BLK_DEVICE_ADD, existing_blkdev->dev);
++
++      mutex_unlock(&blk_notifier_lock);
++}
++EXPORT_SYMBOL_GPL(blk_register_notify);
++
++void blk_unregister_notify(struct notifier_block *nb)
++{
++      mutex_lock(&blk_notifier_lock);
++      raw_notifier_chain_unregister(&blk_notifier_list, nb);
++      mutex_unlock(&blk_notifier_lock);
++}
++EXPORT_SYMBOL_GPL(blk_unregister_notify);
++
++static void blk_notify_work(struct work_struct *work)
++{
++      struct blk_notify_event *ev =
++              container_of(work, struct blk_notify_event, work.work);
++
++      raw_notifier_call_chain(&blk_notifier_list, BLK_DEVICE_ADD, ev->dev);
++      kfree(ev);
++}
++
++static int blk_call_notifier_add(struct device *dev)
++{
++      struct blk_device_list *new_blkdev;
++      struct blk_notify_event *ev;
++
++      new_blkdev = kmalloc(sizeof (*new_blkdev), GFP_KERNEL);
++      if (!new_blkdev)
++              return -ENOMEM;
++
++      ev = kmalloc(sizeof(*ev), GFP_KERNEL);
++      INIT_DEFERRABLE_WORK(&ev->work, blk_notify_work);
++      ev->dev = dev;
++      new_blkdev->dev = dev;
++      mutex_lock(&blk_notifier_lock);
++      list_add_tail(&new_blkdev->list, &blk_devices);
++      schedule_delayed_work(&ev->work, msecs_to_jiffies(500));
++      mutex_unlock(&blk_notifier_lock);
++
++      return 0;
++}
++
++static void blk_call_notifier_remove(struct device *dev)
++{
++      struct blk_device_list *old_blkdev, *tmp;
++
++      mutex_lock(&blk_notifier_lock);
++      list_for_each_entry_safe(old_blkdev, tmp, &blk_devices, list) {
++              if (old_blkdev->dev != dev)
++                      continue;
++
++              list_del(&old_blkdev->list);
++              kfree(old_blkdev);
++      }
++      raw_notifier_call_chain(&blk_notifier_list, BLK_DEVICE_REMOVE, dev);
++      mutex_unlock(&blk_notifier_lock);
++}
++
++static struct class_interface blk_notifications_bus_interface __refdata = {
++      .class = &block_class,
++      .add_dev = &blk_call_notifier_add,
++      .remove_dev = &blk_call_notifier_remove,
++};
++
++static int __init blk_notifications_init(void)
++{
++      return class_interface_register(&blk_notifications_bus_interface);
++}
++device_initcall(blk_notifications_init);
+--- a/include/linux/blkdev.h
++++ b/include/linux/blkdev.h
+@@ -1696,4 +1696,12 @@ static inline bool bdev_can_atomic_write
+ #define DEFINE_IO_COMP_BATCH(name)    struct io_comp_batch name = { }
++
++#ifdef CONFIG_BLOCK_NOTIFIERS
++#define BLK_DEVICE_ADD                1
++#define BLK_DEVICE_REMOVE     2
++extern void blk_register_notify(struct notifier_block *nb);
++extern void blk_unregister_notify(struct notifier_block *nb);
++#endif
++
+ #endif /* _LINUX_BLKDEV_H */
diff --git a/target/linux/generic/pending-6.12/454-nvmem-implement-block-NVMEM-provider.patch b/target/linux/generic/pending-6.12/454-nvmem-implement-block-NVMEM-provider.patch
deleted file mode 100644 (file)
index 3c08f6d..0000000
+++ /dev/null
@@ -1,260 +0,0 @@
-From 9703951cdfe868b130e64d6122420396c2807be8 Mon Sep 17 00:00:00 2001
-From: Daniel Golle <[email protected]>
-Date: Thu, 30 May 2024 03:15:02 +0100
-Subject: [PATCH 5/9] nvmem: implement block NVMEM provider
-
-On embedded devices using an eMMC it is common that one or more partitions
-on the eMMC are used to store MAC addresses and Wi-Fi calibration EEPROM
-data. Allow referencing any block device or partition in Device Tree to
-allow e.g. Ethernet and Wi-Fi drivers accessing them via the NVMEM layer.
-
-Signed-off-by: Daniel Golle <[email protected]>
----
- drivers/nvmem/Kconfig  |  11 +++
- drivers/nvmem/Makefile |   2 +
- drivers/nvmem/block.c  | 197 +++++++++++++++++++++++++++++++++++++++++
- 3 files changed, 210 insertions(+)
- create mode 100644 drivers/nvmem/block.c
-
---- a/drivers/nvmem/Kconfig
-+++ b/drivers/nvmem/Kconfig
-@@ -40,6 +40,17 @@ config NVMEM_APPLE_EFUSES
-         This driver can also be built as a module. If so, the module will
-         be called nvmem-apple-efuses.
-+config NVMEM_BLOCK
-+      tristate "Block device NVMEM provider"
-+      depends on BLOCK
-+      depends on OF
-+      depends on NVMEM
-+      select BLOCK_NOTIFIERS
-+      help
-+        Allow block devices (or partitions) to act as NVMEM prodivers,
-+        typically used with eMMC to store MAC addresses or Wi-Fi
-+        calibration data on embedded devices.
-+
- config NVMEM_BCM_OCOTP
-       tristate "Broadcom On-Chip OTP Controller support"
-       depends on ARCH_BCM_IPROC || COMPILE_TEST
---- a/drivers/nvmem/Makefile
-+++ b/drivers/nvmem/Makefile
-@@ -14,6 +14,8 @@ obj-$(CONFIG_NVMEM_APPLE_EFUSES)     += nvme
- nvmem-apple-efuses-y                  := apple-efuses.o
- obj-$(CONFIG_NVMEM_BCM_OCOTP)         += nvmem-bcm-ocotp.o
- nvmem-bcm-ocotp-y                     := bcm-ocotp.o
-+obj-$(CONFIG_NVMEM_BLOCK)             += nvmem-block.o
-+nvmem-block-y                         := block.o
- obj-$(CONFIG_NVMEM_BRCM_NVRAM)                += nvmem_brcm_nvram.o
- nvmem_brcm_nvram-y                    := brcm_nvram.o
- obj-$(CONFIG_NVMEM_IMX_IIM)           += nvmem-imx-iim.o
---- /dev/null
-+++ b/drivers/nvmem/block.c
-@@ -0,0 +1,208 @@
-+// SPDX-License-Identifier: GPL-2.0-or-later
-+/*
-+ * block device NVMEM provider
-+ *
-+ * Copyright (c) 2024 Daniel Golle <[email protected]>
-+ *
-+ * Useful on devices using a partition on an eMMC for MAC addresses or
-+ * Wi-Fi calibration EEPROM data.
-+ */
-+
-+#include <linux/blkdev.h>
-+#include <linux/nvmem-provider.h>
-+#include <linux/of.h>
-+#include <linux/pagemap.h>
-+#include <linux/property.h>
-+
-+/* List of all NVMEM devices */
-+static LIST_HEAD(nvmem_devices);
-+static DEFINE_MUTEX(devices_mutex);
-+
-+struct blk_nvmem {
-+      struct nvmem_device *nvmem;
-+      struct block_device *bdev;
-+      struct list_head list;
-+};
-+
-+static int blk_nvmem_reg_read(void *priv, unsigned int from,
-+                            void *val, size_t bytes)
-+{
-+      unsigned long offs = from & ~PAGE_MASK, to_read;
-+      pgoff_t f_index = from >> PAGE_SHIFT;
-+      struct address_space *mapping;
-+      struct blk_nvmem *bnv = priv;
-+      size_t bytes_left = bytes;
-+      struct folio *folio;
-+      void *p;
-+      int ret;
-+
-+      if (!bnv->bdev)
-+              return -ENODEV;
-+
-+      if (!bnv->bdev->bd_disk)
-+              return -EINVAL;
-+
-+      if (!bnv->bdev->bd_disk->fops)
-+              return -EIO;
-+
-+      if (!bnv->bdev->bd_disk->fops->open)
-+              return -EIO;
-+
-+      ret = bnv->bdev->bd_disk->fops->open(bnv->bdev->bd_disk, BLK_OPEN_READ);
-+      if (ret)
-+              return ret;
-+
-+      mapping = bnv->bdev->bd_inode->i_mapping;
-+
-+      while (bytes_left) {
-+              folio = read_mapping_folio(mapping, f_index++, NULL);
-+              if (IS_ERR(folio)) {
-+                      ret = PTR_ERR(folio);
-+                      goto err_release_bdev;
-+              }
-+              to_read = min_t(unsigned long, bytes_left, PAGE_SIZE - offs);
-+              p = folio_address(folio) + offset_in_folio(folio, offs);
-+              memcpy(val, p, to_read);
-+              offs = 0;
-+              bytes_left -= to_read;
-+              val += to_read;
-+              folio_put(folio);
-+      }
-+
-+err_release_bdev:
-+      bnv->bdev->bd_disk->fops->release(bnv->bdev->bd_disk);
-+
-+      return ret;
-+}
-+
-+static int blk_nvmem_register(struct device *dev)
-+{
-+      struct device_node *np = dev_of_node(dev);
-+      struct block_device *bdev = dev_to_bdev(dev);
-+      struct nvmem_config config = {};
-+      struct blk_nvmem *bnv;
-+
-+      /* skip devices which do not have a device tree node */
-+      if (!np)
-+              return 0;
-+
-+      /* skip devices without an nvmem layout defined */
-+      if (!of_get_child_by_name(np, "nvmem-layout"))
-+              return 0;
-+
-+      /*
-+       * skip devices which don't have GENHD_FL_NVMEM set
-+       *
-+       * This flag is used for mtdblock and ubiblock devices because
-+       * both, MTD and UBI already implement their own NVMEM provider.
-+       * To avoid registering multiple NVMEM providers for the same
-+       * device node, don't register the block NVMEM provider for them.
-+       */
-+      if (!(bdev->bd_disk->flags & GENHD_FL_NVMEM))
-+              return 0;
-+
-+      /*
-+       * skip block device too large to be represented as NVMEM devices
-+       * which are using an 'int' as address
-+       */
-+      if (bdev_nr_bytes(bdev) > INT_MAX)
-+              return -EFBIG;
-+
-+      bnv = kzalloc(sizeof(struct blk_nvmem), GFP_KERNEL);
-+      if (!bnv)
-+              return -ENOMEM;
-+
-+      config.id = NVMEM_DEVID_NONE;
-+      config.dev = &bdev->bd_device;
-+      config.name = dev_name(&bdev->bd_device);
-+      config.owner = THIS_MODULE;
-+      config.priv = bnv;
-+      config.reg_read = blk_nvmem_reg_read;
-+      config.size = bdev_nr_bytes(bdev);
-+      config.word_size = 1;
-+      config.stride = 1;
-+      config.read_only = true;
-+      config.root_only = true;
-+      config.ignore_wp = true;
-+      config.of_node = to_of_node(dev->fwnode);
-+
-+      bnv->bdev = bdev;
-+      bnv->nvmem = nvmem_register(&config);
-+      if (IS_ERR(bnv->nvmem)) {
-+              dev_err_probe(&bdev->bd_device, PTR_ERR(bnv->nvmem),
-+                            "Failed to register NVMEM device\n");
-+
-+              kfree(bnv);
-+              return PTR_ERR(bnv->nvmem);
-+      }
-+
-+      mutex_lock(&devices_mutex);
-+      list_add_tail(&bnv->list, &nvmem_devices);
-+      mutex_unlock(&devices_mutex);
-+
-+      return 0;
-+}
-+
-+static void blk_nvmem_unregister(struct device *dev)
-+{
-+      struct block_device *bdev = dev_to_bdev(dev);
-+      struct blk_nvmem *bnv_c, *bnv = NULL;
-+
-+      mutex_lock(&devices_mutex);
-+      list_for_each_entry(bnv_c, &nvmem_devices, list) {
-+              if (bnv_c->bdev == bdev) {
-+                      bnv = bnv_c;
-+                      break;
-+              }
-+      }
-+
-+      if (!bnv) {
-+              mutex_unlock(&devices_mutex);
-+              return;
-+      }
-+
-+      list_del(&bnv->list);
-+      mutex_unlock(&devices_mutex);
-+      nvmem_unregister(bnv->nvmem);
-+      kfree(bnv);
-+}
-+
-+static int blk_nvmem_handler(struct notifier_block *this, unsigned long code, void *obj)
-+{
-+      struct device *dev = (struct device *)obj;
-+
-+      switch (code) {
-+      case BLK_DEVICE_ADD:
-+              return blk_nvmem_register(dev);
-+      case BLK_DEVICE_REMOVE:
-+              blk_nvmem_unregister(dev);
-+              break;
-+      default:
-+              return -EINVAL;
-+      }
-+
-+      return 0;
-+}
-+
-+static struct notifier_block blk_nvmem_notifier = {
-+      .notifier_call = blk_nvmem_handler,
-+};
-+
-+static int __init blk_nvmem_init(void)
-+{
-+      blk_register_notify(&blk_nvmem_notifier);
-+
-+      return 0;
-+}
-+
-+static void __exit blk_nvmem_exit(void)
-+{
-+      blk_unregister_notify(&blk_nvmem_notifier);
-+}
-+
-+module_init(blk_nvmem_init);
-+module_exit(blk_nvmem_exit);
-+
-+MODULE_LICENSE("GPL");
-+MODULE_AUTHOR("Daniel Golle <[email protected]>");
-+MODULE_DESCRIPTION("block device NVMEM provider");
diff --git a/target/linux/generic/pending-6.12/455-block-add-new-genhd-flag-GENHD_FL_NVMEM.patch b/target/linux/generic/pending-6.12/455-block-add-new-genhd-flag-GENHD_FL_NVMEM.patch
new file mode 100644 (file)
index 0000000..4f9a26f
--- /dev/null
@@ -0,0 +1,29 @@
+From 2b28bf485b283991eea9f00c5831c1c39c73991f Mon Sep 17 00:00:00 2001
+From: Daniel Golle <[email protected]>
+Date: Thu, 21 Mar 2024 19:33:49 +0000
+Subject: [PATCH 6/8] block: add new genhd flag GENHD_FL_NVMEM
+
+Add new flag to destinguish block devices which may act as an NVMEM
+provider.
+
+Signed-off-by: Daniel Golle <[email protected]>
+---
+ include/linux/blkdev.h | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/include/linux/blkdev.h
++++ b/include/linux/blkdev.h
+@@ -82,11 +82,13 @@ struct partition_meta_info {
+  * ``GENHD_FL_NO_PART``: partition support is disabled.  The kernel will not
+  * scan for partitions from add_disk, and users can't add partitions manually.
+  *
++ * ``GENHD_FL_NVMEM``: the block device should be considered as NVMEM provider.
+  */
+ enum {
+       GENHD_FL_REMOVABLE                      = 1 << 0,
+       GENHD_FL_HIDDEN                         = 1 << 1,
+       GENHD_FL_NO_PART                        = 1 << 2,
++      GENHD_FL_NVMEM                          = 1 << 3,
+ };
+ enum {
diff --git a/target/linux/generic/pending-6.12/455-dt-bindings-mmc-mmc-card-add-block-device-nodes.patch b/target/linux/generic/pending-6.12/455-dt-bindings-mmc-mmc-card-add-block-device-nodes.patch
deleted file mode 100644 (file)
index 74e6c82..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-From f7ec19b34d1b7e934a58ceb102369bbd30b2631d Mon Sep 17 00:00:00 2001
-From: Daniel Golle <[email protected]>
-Date: Thu, 30 May 2024 03:15:11 +0100
-Subject: [PATCH 6/9] dt-bindings: mmc: mmc-card: add block device nodes
-
-Add nodes representing the block devices exposed by an MMC device
-including an example involving nvmem-cells.
-
-Signed-off-by: Daniel Golle <[email protected]>
----
- .../devicetree/bindings/mmc/mmc-card.yaml     | 45 +++++++++++++++++++
- 1 file changed, 45 insertions(+)
-
---- a/Documentation/devicetree/bindings/mmc/mmc-card.yaml
-+++ b/Documentation/devicetree/bindings/mmc/mmc-card.yaml
-@@ -26,6 +26,18 @@ properties:
-       Use this to indicate that the mmc-card has a broken hpi
-       implementation, and that hpi should not be used.
-+  block:
-+    $ref: /schemas/block/block-device.yaml#
-+    description:
-+      Represents the block storage provided by an SD card or the
-+      main hardware partition of an eMMC.
-+
-+patternProperties:
-+  '^boot[0-9]+':
-+    $ref: /schemas/block/block-device.yaml#
-+    description:
-+      Represents a boot hardware partition on an eMMC.
-+
- required:
-   - compatible
-   - reg
-@@ -42,6 +54,39 @@ examples:
-             compatible = "mmc-card";
-             reg = <0>;
-             broken-hpi;
-+
-+            block {
-+                partitions {
-+                    cal_data: block-partition-rf {
-+                        partnum = <3>;
-+                        partname = "rf";
-+
-+                        nvmem-layout {
-+                            compatible = "fixed-layout";
-+                            #address-cells = <1>;
-+                            #size-cells = <1>;
-+
-+                            eeprom@0 {
-+                                reg = <0x0 0x1000>;
-+                            };
-+                        };
-+                    };
-+                };
-+            };
-+
-+            boot1 {
-+                nvmem-layout {
-+                    compatible = "fixed-layout";
-+                    #address-cells = <1>;
-+                    #size-cells = <1>;
-+
-+                    macaddr: macaddr@a {
-+                        compatible = "mac-base";
-+                        reg = <0xa 0x6>;
-+                        #nvmem-cell-cells = <1>;
-+                    };
-+                };
-+            };
-         };
-     };
diff --git a/target/linux/generic/pending-6.12/456-mmc-core-set-card-fwnode_handle.patch b/target/linux/generic/pending-6.12/456-mmc-core-set-card-fwnode_handle.patch
deleted file mode 100644 (file)
index 85438df..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-From 043c4f88476cc0f29c9bf82a8a516f58d848e1cd Mon Sep 17 00:00:00 2001
-From: Daniel Golle <[email protected]>
-Date: Thu, 30 May 2024 03:15:25 +0100
-Subject: [PATCH 7/9] mmc: core: set card fwnode_handle
-
-Set fwnode in case it isn't set yet and of_node is present.
-
-Signed-off-by: Daniel Golle <[email protected]>
----
- drivers/mmc/core/bus.c | 2 ++
- 1 file changed, 2 insertions(+)
-
---- a/drivers/mmc/core/bus.c
-+++ b/drivers/mmc/core/bus.c
-@@ -368,6 +368,8 @@ int mmc_add_card(struct mmc_card *card)
-       mmc_add_card_debugfs(card);
-       card->dev.of_node = mmc_of_find_child_device(card->host, 0);
-+      if (card->dev.of_node && !card->dev.fwnode)
-+              card->dev.fwnode = &card->dev.of_node->fwnode;
-       device_enable_async_suspend(&card->dev);
diff --git a/target/linux/generic/pending-6.12/456-nvmem-implement-block-NVMEM-provider.patch b/target/linux/generic/pending-6.12/456-nvmem-implement-block-NVMEM-provider.patch
new file mode 100644 (file)
index 0000000..563b9f1
--- /dev/null
@@ -0,0 +1,250 @@
+From 26ae98bf77fdbd60536fe5c2175e528469b9ac9a Mon Sep 17 00:00:00 2001
+From: Daniel Golle <[email protected]>
+Date: Wed, 15 May 2024 18:18:37 +0300
+Subject: [PATCH 7/8] nvmem: implement block NVMEM provider
+
+On embedded devices using an eMMC it is common that one or more partitions
+on the eMMC are used to store MAC addresses and Wi-Fi calibration EEPROM
+data. Allow referencing any block device or partition in Device Tree to
+allow e.g. Ethernet and Wi-Fi drivers accessing them via the NVMEM layer.
+
+Signed-off-by: Daniel Golle <[email protected]>
+---
+ drivers/nvmem/Kconfig  |  11 +++
+ drivers/nvmem/Makefile |   2 +
+ drivers/nvmem/block.c  | 198 +++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 211 insertions(+)
+ create mode 100644 drivers/nvmem/block.c
+
+--- a/drivers/nvmem/Kconfig
++++ b/drivers/nvmem/Kconfig
+@@ -40,6 +40,17 @@ config NVMEM_APPLE_EFUSES
+         This driver can also be built as a module. If so, the module will
+         be called nvmem-apple-efuses.
++config NVMEM_BLOCK
++      tristate "Block device NVMEM provider"
++      depends on BLOCK
++      depends on OF
++      depends on NVMEM
++      select BLOCK_NOTIFIERS
++      help
++        Allow block devices (or partitions) to act as NVMEM prodivers,
++        typically used with eMMC to store MAC addresses or Wi-Fi
++        calibration data on embedded devices.
++
+ config NVMEM_BCM_OCOTP
+       tristate "Broadcom On-Chip OTP Controller support"
+       depends on ARCH_BCM_IPROC || COMPILE_TEST
+--- a/drivers/nvmem/Makefile
++++ b/drivers/nvmem/Makefile
+@@ -14,6 +14,8 @@ obj-$(CONFIG_NVMEM_APPLE_EFUSES)     += nvme
+ nvmem-apple-efuses-y                  := apple-efuses.o
+ obj-$(CONFIG_NVMEM_BCM_OCOTP)         += nvmem-bcm-ocotp.o
+ nvmem-bcm-ocotp-y                     := bcm-ocotp.o
++obj-$(CONFIG_NVMEM_BLOCK)             += nvmem-block.o
++nvmem-block-y                         := block.o
+ obj-$(CONFIG_NVMEM_BRCM_NVRAM)                += nvmem_brcm_nvram.o
+ nvmem_brcm_nvram-y                    := brcm_nvram.o
+ obj-$(CONFIG_NVMEM_IMX_IIM)           += nvmem-imx-iim.o
+--- /dev/null
++++ b/drivers/nvmem/block.c
+@@ -0,0 +1,198 @@
++// SPDX-License-Identifier: GPL-2.0-or-later
++/*
++ * block device NVMEM provider
++ *
++ * Copyright (c) 2024 Daniel Golle <[email protected]>
++ *
++ * Useful on devices using a partition on an eMMC for MAC addresses or
++ * Wi-Fi calibration EEPROM data.
++ */
++
++#include <linux/blkdev.h>
++#include <linux/nvmem-provider.h>
++#include <linux/of.h>
++#include <linux/pagemap.h>
++#include <linux/property.h>
++
++/* List of all NVMEM devices */
++static LIST_HEAD(nvmem_devices);
++static DEFINE_MUTEX(devices_mutex);
++
++struct blk_nvmem {
++      struct nvmem_device     *nvmem;
++      struct device           *dev;
++      struct list_head        list;
++};
++
++static int blk_nvmem_reg_read(void *priv, unsigned int from,
++                            void *val, size_t bytes)
++{
++      blk_mode_t mode = BLK_OPEN_READ | BLK_OPEN_RESTRICT_WRITES;
++      unsigned long offs = from & ~PAGE_MASK, to_read;
++      pgoff_t f_index = from >> PAGE_SHIFT;
++      struct blk_nvmem *bnv = priv;
++      size_t bytes_left = bytes;
++      struct file *bdev_file;
++      struct folio *folio;
++      void *p;
++      int ret = 0;
++
++      bdev_file = bdev_file_open_by_dev(bnv->dev->devt, mode, priv, NULL);
++      if (!bdev_file)
++              return -ENODEV;
++
++      if (IS_ERR(bdev_file))
++              return PTR_ERR(bdev_file);
++
++      while (bytes_left) {
++              folio = read_mapping_folio(bdev_file->f_mapping, f_index++, NULL);
++              if (IS_ERR(folio)) {
++                      ret = PTR_ERR(folio);
++                      goto err_release_bdev;
++              }
++              to_read = min_t(unsigned long, bytes_left, PAGE_SIZE - offs);
++              p = folio_address(folio) + offset_in_folio(folio, offs);
++              memcpy(val, p, to_read);
++              offs = 0;
++              bytes_left -= to_read;
++              val += to_read;
++              folio_put(folio);
++      }
++
++err_release_bdev:
++      fput(bdev_file);
++
++      return ret;
++}
++
++static int blk_nvmem_register(struct device *dev)
++{
++      struct block_device *bdev = dev_to_bdev(dev);
++      struct device_node *np = dev_of_node(dev);
++      struct nvmem_config config = {};
++      struct blk_nvmem *bnv;
++
++      /* skip devices which do not have a device tree node */
++      if (!np)
++              return 0;
++
++      /* skip devices without an nvmem layout defined */
++      if (!of_get_child_by_name(np, "nvmem-layout"))
++              return 0;
++
++      /*
++       * skip devices which don't have GENHD_FL_NVMEM set
++       *
++       * This flag is used for mtdblock and ubiblock devices because
++       * both, MTD and UBI already implement their own NVMEM provider.
++       * To avoid registering multiple NVMEM providers for the same
++       * device node, don't register the block NVMEM provider for them.
++       */
++      if (!(bdev->bd_disk->flags & GENHD_FL_NVMEM))
++              return 0;
++
++      /*
++       * skip block device too large to be represented as NVMEM devices
++       * which are using an 'int' as address
++       */
++      if (bdev_nr_bytes(bdev) > INT_MAX)
++              return -EFBIG;
++
++      bnv = kzalloc(sizeof(struct blk_nvmem), GFP_KERNEL);
++      if (!bnv)
++              return -ENOMEM;
++
++      config.id = NVMEM_DEVID_NONE;
++      config.dev = &bdev->bd_device;
++      config.name = dev_name(&bdev->bd_device);
++      config.owner = THIS_MODULE;
++      config.priv = bnv;
++      config.reg_read = blk_nvmem_reg_read;
++      config.size = bdev_nr_bytes(bdev);
++      config.word_size = 1;
++      config.stride = 1;
++      config.read_only = true;
++      config.root_only = true;
++      config.ignore_wp = true;
++      config.of_node = to_of_node(dev->fwnode);
++
++      bnv->dev = &bdev->bd_device;
++      bnv->nvmem = nvmem_register(&config);
++      if (IS_ERR(bnv->nvmem)) {
++              dev_err_probe(&bdev->bd_device, PTR_ERR(bnv->nvmem),
++                            "Failed to register NVMEM device\n");
++
++              kfree(bnv);
++              return PTR_ERR(bnv->nvmem);
++      }
++
++      mutex_lock(&devices_mutex);
++      list_add_tail(&bnv->list, &nvmem_devices);
++      mutex_unlock(&devices_mutex);
++
++      return 0;
++}
++
++static void blk_nvmem_unregister(struct device *dev)
++{
++      struct blk_nvmem *bnv_c, *bnv = NULL;
++
++      mutex_lock(&devices_mutex);
++      list_for_each_entry(bnv_c, &nvmem_devices, list) {
++              if (bnv_c->dev == dev) {
++                      bnv = bnv_c;
++                      break;
++              }
++      }
++
++      if (!bnv) {
++              mutex_unlock(&devices_mutex);
++              return;
++      }
++
++      list_del(&bnv->list);
++      mutex_unlock(&devices_mutex);
++      nvmem_unregister(bnv->nvmem);
++      kfree(bnv);
++}
++
++static int blk_nvmem_handler(struct notifier_block *this, unsigned long code, void *obj)
++{
++      struct device *dev = (struct device *)obj;
++
++      switch (code) {
++      case BLK_DEVICE_ADD:
++              return blk_nvmem_register(dev);
++              break;
++      case BLK_DEVICE_REMOVE:
++              blk_nvmem_unregister(dev);
++              break;
++      default:
++              return -EINVAL;
++      }
++
++      return 0;
++}
++
++static struct notifier_block blk_nvmem_notifier = {
++      .notifier_call = blk_nvmem_handler,
++};
++
++static int __init blk_nvmem_init(void)
++{
++      blk_register_notify(&blk_nvmem_notifier);
++
++      return 0;
++}
++
++static void __exit blk_nvmem_exit(void)
++{
++      blk_unregister_notify(&blk_nvmem_notifier);
++}
++
++module_init(blk_nvmem_init);
++module_exit(blk_nvmem_exit);
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Daniel Golle <[email protected]>");
++MODULE_DESCRIPTION("block device NVMEM provider");
diff --git a/target/linux/generic/pending-6.12/457-mmc-block-set-GENHD_FL_NVMEM.patch b/target/linux/generic/pending-6.12/457-mmc-block-set-GENHD_FL_NVMEM.patch
new file mode 100644 (file)
index 0000000..955fa66
--- /dev/null
@@ -0,0 +1,22 @@
+From caac69565748349a3e532130a891e18dd5c36c5e Mon Sep 17 00:00:00 2001
+From: Daniel Golle <[email protected]>
+Date: Thu, 20 Jul 2023 17:36:44 +0100
+Subject: [PATCH 8/8] mmc: block: set GENHD_FL_NVMEM
+
+Set flag to consider MMC block devices as NVMEM providers.
+
+Signed-off-by: Daniel Golle <[email protected]>
+---
+ drivers/mmc/core/block.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/mmc/core/block.c
++++ b/drivers/mmc/core/block.c
+@@ -2644,6 +2644,7 @@ static struct mmc_blk_data *mmc_blk_allo
+       md->disk->major = MMC_BLOCK_MAJOR;
+       md->disk->minors = perdev_minors;
+       md->disk->first_minor = devidx * perdev_minors;
++      md->disk->flags = GENHD_FL_NVMEM;
+       md->disk->fops = &mmc_bdops;
+       md->disk->private_data = md;
+       md->parent = parent;
diff --git a/target/linux/generic/pending-6.12/457-mmc-block-set-fwnode-of-disk-devices.patch b/target/linux/generic/pending-6.12/457-mmc-block-set-fwnode-of-disk-devices.patch
deleted file mode 100644 (file)
index e37d15b..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-From ef3e38fec26901b71975d7e810a2df6b8bd54a8e Mon Sep 17 00:00:00 2001
-From: Daniel Golle <[email protected]>
-Date: Thu, 30 May 2024 03:15:36 +0100
-Subject: [PATCH 8/9] mmc: block: set fwnode of disk devices
-
-Set fwnode of disk devices to 'block', 'boot0' and 'boot1' subnodes of
-the mmc-card. This is done in preparation for having the eMMC act as
-NVMEM provider.
-
-Signed-off-by: Daniel Golle <[email protected]>
----
- drivers/mmc/core/block.c | 7 +++++++
- 1 file changed, 7 insertions(+)
-
---- a/drivers/mmc/core/block.c
-+++ b/drivers/mmc/core/block.c
-@@ -2678,6 +2678,10 @@ static struct mmc_blk_data *mmc_blk_allo
-       if (area_type == MMC_BLK_DATA_AREA_MAIN)
-               dev_set_drvdata(&card->dev, md);
-       disk_fwnode = mmc_blk_get_partitions_node(parent, subname);
-+      if (!disk_fwnode)
-+              disk_fwnode = device_get_named_child_node(subname ? md->parent->parent :
-+                                                        md->parent,
-+                                                        subname ? subname : "block");
-       ret = add_disk_fwnode(md->parent, md->disk, mmc_disk_attr_groups,
-                             disk_fwnode);
-       if (ret)
diff --git a/target/linux/generic/pending-6.12/458-mmc-block-set-GENHD_FL_NVMEM.patch b/target/linux/generic/pending-6.12/458-mmc-block-set-GENHD_FL_NVMEM.patch
deleted file mode 100644 (file)
index 7ef0d01..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-From 7903b50441000365a6fe5badb39735889f562252 Mon Sep 17 00:00:00 2001
-From: Daniel Golle <[email protected]>
-Date: Thu, 30 May 2024 03:15:46 +0100
-Subject: [PATCH 9/9] mmc: block: set GENHD_FL_NVMEM
-
-Set flag to consider MMC block devices as NVMEM providers.
-
-Signed-off-by: Daniel Golle <[email protected]>
----
- drivers/mmc/core/block.c | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/drivers/mmc/core/block.c
-+++ b/drivers/mmc/core/block.c
-@@ -2644,6 +2644,7 @@ static struct mmc_blk_data *mmc_blk_allo
-       md->disk->major = MMC_BLOCK_MAJOR;
-       md->disk->minors = perdev_minors;
-       md->disk->first_minor = devidx * perdev_minors;
-+      md->disk->flags = GENHD_FL_NVMEM;
-       md->disk->fops = &mmc_bdops;
-       md->disk->private_data = md;
-       md->parent = parent;