generic: 6.12: update block NVMEM driver
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 <daniel@makrotopia.org>
This commit is contained in:
parent
2ce11c911d
commit
fa0f130764
14 changed files with 810 additions and 515 deletions
|
@ -0,0 +1,123 @@
|
||||||
|
From decc6959a423c8617e87244fd269129fc4e7d0e6 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Daniel Golle <daniel@makrotopia.org>
|
||||||
|
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 <daniel@makrotopia.org>
|
||||||
|
---
|
||||||
|
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",
|
|
@ -1,120 +0,0 @@
|
||||||
From 3245921a87154bdfbe7a55d743ea62dd559a8fb0 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Daniel Golle <daniel@makrotopia.org>
|
|
||||||
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 <daniel@makrotopia.org>
|
|
||||||
---
|
|
||||||
.../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 <daniel@makrotopia.org>
|
|
||||||
+
|
|
||||||
+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 <daniel@makrotopia.org>
|
|
||||||
+
|
|
||||||
+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 <daniel@makrotopia.org>
|
|
||||||
+
|
|
||||||
+patternProperties:
|
|
||||||
+ "^block-partition-.+$":
|
|
||||||
+ $ref: partition.yaml
|
|
||||||
+
|
|
||||||
+unevaluatedProperties: false
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
From 5d265996597a6b0d654bbeda1bc3bae197061de7 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Daniel Golle <daniel@makrotopia.org>
|
||||||
|
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 <daniel@makrotopia.org>
|
||||||
|
---
|
||||||
|
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;
|
|
@ -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 <daniel@makrotopia.org>
|
|
||||||
X-Patchwork-Id: 13747816
|
|
||||||
Date: Tue, 30 Jul 2024 20:25:59 +0100
|
|
||||||
From: Daniel Golle <daniel@makrotopia.org>
|
|
||||||
To: Rob Herring <robh@kernel.org>, Krzysztof Kozlowski <krzk+dt@kernel.org>,
|
|
||||||
Conor Dooley <conor+dt@kernel.org>, Jens Axboe <axboe@kernel.dk>,
|
|
||||||
Daniel Golle <daniel@makrotopia.org>, Christian Brauner <brauner@kernel.org>,
|
|
||||||
Al Viro <viro@zeniv.linux.org.uk>, Li Lingfeng <lilingfeng3@huawei.com>,
|
|
||||||
Ming Lei <ming.lei@redhat.com>, Christian Heusel <christian@heusel.eu>,
|
|
||||||
=?utf-8?b?UmFmYcWCIE1pxYJlY2tp?= <rafal@milecki.pl>,
|
|
||||||
Felix Fietkau <nbd@nbd.name>, John Crispin <john@phrozen.org>,
|
|
||||||
Chad Monroe <chad.monroe@adtran.com>, Yangyu Chen <cyy@cyyself.name>,
|
|
||||||
Tianling Shen <cnsztl@immortalwrt.org>, Chuanhong Guo <gch981213@gmail.com>,
|
|
||||||
Chen Minqiang <ptpt52@gmail.com>, devicetree@vger.kernel.org,
|
|
||||||
linux-kernel@vger.kernel.org, linux-block@vger.kernel.org
|
|
||||||
Subject: [PATCH v5 2/4] block: partitions: populate fwnode
|
|
||||||
Message-ID:
|
|
||||||
<3051ac090ad3b3e2f5adb6b67c923261ead729a5.1722365899.git.daniel@makrotopia.org>
|
|
||||||
References: <cover.1722365899.git.daniel@makrotopia.org>
|
|
||||||
Precedence: bulk
|
|
||||||
X-Mailing-List: linux-block@vger.kernel.org
|
|
||||||
List-Id: <linux-block.vger.kernel.org>
|
|
||||||
List-Subscribe: <mailto:linux-block+subscribe@vger.kernel.org>
|
|
||||||
List-Unsubscribe: <mailto:linux-block+unsubscribe@vger.kernel.org>
|
|
||||||
MIME-Version: 1.0
|
|
||||||
Content-Disposition: inline
|
|
||||||
In-Reply-To: <cover.1722365899.git.daniel@makrotopia.org>
|
|
||||||
|
|
||||||
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 <daniel@makrotopia.org>
|
|
||||||
---
|
|
||||||
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);
|
|
|
@ -0,0 +1,498 @@
|
||||||
|
From d4e82837c8b86ff2c21fa923271908988bc72faa Mon Sep 17 00:00:00 2001
|
||||||
|
From: Daniel Golle <daniel@makrotopia.org>
|
||||||
|
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 <daniel@makrotopia.org>
|
||||||
|
---
|
||||||
|
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);
|
|
@ -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 <daniel@makrotopia.org>
|
|
||||||
X-Patchwork-Id: 13747818
|
|
||||||
Date: Tue, 30 Jul 2024 20:27:07 +0100
|
|
||||||
From: Daniel Golle <daniel@makrotopia.org>
|
|
||||||
To: Rob Herring <robh@kernel.org>, Krzysztof Kozlowski <krzk+dt@kernel.org>,
|
|
||||||
Conor Dooley <conor+dt@kernel.org>, Jens Axboe <axboe@kernel.dk>,
|
|
||||||
Daniel Golle <daniel@makrotopia.org>, Christian Brauner <brauner@kernel.org>,
|
|
||||||
Al Viro <viro@zeniv.linux.org.uk>, Li Lingfeng <lilingfeng3@huawei.com>,
|
|
||||||
Ming Lei <ming.lei@redhat.com>, Christian Heusel <christian@heusel.eu>,
|
|
||||||
=?utf-8?b?UmFmYcWCIE1pxYJlY2tp?= <rafal@milecki.pl>,
|
|
||||||
Felix Fietkau <nbd@nbd.name>, John Crispin <john@phrozen.org>,
|
|
||||||
Chad Monroe <chad.monroe@adtran.com>, Yangyu Chen <cyy@cyyself.name>,
|
|
||||||
Tianling Shen <cnsztl@immortalwrt.org>, Chuanhong Guo <gch981213@gmail.com>,
|
|
||||||
Chen Minqiang <ptpt52@gmail.com>, devicetree@vger.kernel.org,
|
|
||||||
linux-kernel@vger.kernel.org, linux-block@vger.kernel.org
|
|
||||||
Subject: [PATCH v5 4/4] block: add new genhd flag GENHD_FL_NVMEM
|
|
||||||
Message-ID:
|
|
||||||
<311ea569c23ce14e2896cd3b069dc494c58c49c2.1722365899.git.daniel@makrotopia.org>
|
|
||||||
References: <cover.1722365899.git.daniel@makrotopia.org>
|
|
||||||
Precedence: bulk
|
|
||||||
X-Mailing-List: linux-block@vger.kernel.org
|
|
||||||
List-Id: <linux-block.vger.kernel.org>
|
|
||||||
List-Subscribe: <mailto:linux-block+subscribe@vger.kernel.org>
|
|
||||||
List-Unsubscribe: <mailto:linux-block+unsubscribe@vger.kernel.org>
|
|
||||||
MIME-Version: 1.0
|
|
||||||
Content-Disposition: inline
|
|
||||||
In-Reply-To: <cover.1722365899.git.daniel@makrotopia.org>
|
|
||||||
|
|
||||||
Add new flag to destinguish block devices which may act as an NVMEM
|
|
||||||
provider.
|
|
||||||
|
|
||||||
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
|
||||||
---
|
|
||||||
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 {
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
From f28e36c19b927671d93ccd2b5de3d518fccf721e Mon Sep 17 00:00:00 2001
|
||||||
|
From: Daniel Golle <daniel@makrotopia.org>
|
||||||
|
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 <daniel@makrotopia.org>
|
||||||
|
---
|
||||||
|
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,
|
|
@ -1,34 +1,7 @@
|
||||||
From patchwork Tue Jul 30 19:26:42 2024
|
From 858df9db80c1568db255659baca7602504f823af Mon Sep 17 00:00:00 2001
|
||||||
Content-Type: text/plain; charset="utf-8"
|
|
||||||
MIME-Version: 1.0
|
|
||||||
Content-Transfer-Encoding: 7bit
|
|
||||||
X-Patchwork-Submitter: Daniel Golle <daniel@makrotopia.org>
|
|
||||||
X-Patchwork-Id: 13747817
|
|
||||||
Date: Tue, 30 Jul 2024 20:26:42 +0100
|
|
||||||
From: Daniel Golle <daniel@makrotopia.org>
|
From: Daniel Golle <daniel@makrotopia.org>
|
||||||
To: Rob Herring <robh@kernel.org>, Krzysztof Kozlowski <krzk+dt@kernel.org>,
|
Date: Wed, 15 May 2024 08:19:51 +0100
|
||||||
Conor Dooley <conor+dt@kernel.org>, Jens Axboe <axboe@kernel.dk>,
|
Subject: [PATCH 5/8] block: add support for notifications
|
||||||
Daniel Golle <daniel@makrotopia.org>, Christian Brauner <brauner@kernel.org>,
|
|
||||||
Al Viro <viro@zeniv.linux.org.uk>, Li Lingfeng <lilingfeng3@huawei.com>,
|
|
||||||
Ming Lei <ming.lei@redhat.com>, Christian Heusel <christian@heusel.eu>,
|
|
||||||
=?utf-8?b?UmFmYcWCIE1pxYJlY2tp?= <rafal@milecki.pl>,
|
|
||||||
Felix Fietkau <nbd@nbd.name>, John Crispin <john@phrozen.org>,
|
|
||||||
Chad Monroe <chad.monroe@adtran.com>, Yangyu Chen <cyy@cyyself.name>,
|
|
||||||
Tianling Shen <cnsztl@immortalwrt.org>, Chuanhong Guo <gch981213@gmail.com>,
|
|
||||||
Chen Minqiang <ptpt52@gmail.com>, devicetree@vger.kernel.org,
|
|
||||||
linux-kernel@vger.kernel.org, linux-block@vger.kernel.org
|
|
||||||
Subject: [PATCH v5 3/4] block: add support for notifications
|
|
||||||
Message-ID:
|
|
||||||
<ca0022886e8f211a323a716653a1396a3bc91653.1722365899.git.daniel@makrotopia.org>
|
|
||||||
References: <cover.1722365899.git.daniel@makrotopia.org>
|
|
||||||
Precedence: bulk
|
|
||||||
X-Mailing-List: linux-block@vger.kernel.org
|
|
||||||
List-Id: <linux-block.vger.kernel.org>
|
|
||||||
List-Subscribe: <mailto:linux-block+subscribe@vger.kernel.org>
|
|
||||||
List-Unsubscribe: <mailto:linux-block+unsubscribe@vger.kernel.org>
|
|
||||||
MIME-Version: 1.0
|
|
||||||
Content-Disposition: inline
|
|
||||||
In-Reply-To: <cover.1722365899.git.daniel@makrotopia.org>
|
|
||||||
|
|
||||||
Add notifier block to notify other subsystems about the addition or
|
Add notifier block to notify other subsystems about the addition or
|
||||||
removal of block devices.
|
removal of block devices.
|
||||||
|
@ -37,9 +10,9 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||||
---
|
---
|
||||||
block/Kconfig | 6 +++
|
block/Kconfig | 6 +++
|
||||||
block/Makefile | 1 +
|
block/Makefile | 1 +
|
||||||
block/blk-notify.c | 87 ++++++++++++++++++++++++++++++++++++++++++
|
block/blk-notify.c | 107 +++++++++++++++++++++++++++++++++++++++++
|
||||||
include/linux/blkdev.h | 11 ++++++
|
include/linux/blkdev.h | 8 +++
|
||||||
4 files changed, 105 insertions(+)
|
4 files changed, 122 insertions(+)
|
||||||
create mode 100644 block/blk-notify.c
|
create mode 100644 block/blk-notify.c
|
||||||
|
|
||||||
--- a/block/Kconfig
|
--- a/block/Kconfig
|
||||||
|
@ -66,7 +39,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||||
+obj-$(CONFIG_BLOCK_NOTIFIERS) += blk-notify.o
|
+obj-$(CONFIG_BLOCK_NOTIFIERS) += blk-notify.o
|
||||||
--- /dev/null
|
--- /dev/null
|
||||||
+++ b/block/blk-notify.c
|
+++ b/block/blk-notify.c
|
||||||
@@ -0,0 +1,87 @@
|
@@ -0,0 +1,107 @@
|
||||||
+// SPDX-License-Identifier: GPL-2.0-or-later
|
+// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
+/*
|
+/*
|
||||||
+ * Notifiers for addition and removal of block devices
|
+ * Notifiers for addition and removal of block devices
|
||||||
|
@ -77,6 +50,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||||
+#include <linux/list.h>
|
+#include <linux/list.h>
|
||||||
+#include <linux/mutex.h>
|
+#include <linux/mutex.h>
|
||||||
+#include <linux/notifier.h>
|
+#include <linux/notifier.h>
|
||||||
|
+#include <linux/workqueue.h>
|
||||||
+
|
+
|
||||||
+#include "blk.h"
|
+#include "blk.h"
|
||||||
+
|
+
|
||||||
|
@ -89,6 +63,11 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||||
+static DEFINE_MUTEX(blk_notifier_lock);
|
+static DEFINE_MUTEX(blk_notifier_lock);
|
||||||
+static LIST_HEAD(blk_devices);
|
+static LIST_HEAD(blk_devices);
|
||||||
+
|
+
|
||||||
|
+struct blk_notify_event {
|
||||||
|
+ struct delayed_work work;
|
||||||
|
+ struct device *dev;
|
||||||
|
+};
|
||||||
|
+
|
||||||
+void blk_register_notify(struct notifier_block *nb)
|
+void blk_register_notify(struct notifier_block *nb)
|
||||||
+{
|
+{
|
||||||
+ struct blk_device_list *existing_blkdev;
|
+ struct blk_device_list *existing_blkdev;
|
||||||
|
@ -111,19 +90,33 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||||
+}
|
+}
|
||||||
+EXPORT_SYMBOL_GPL(blk_unregister_notify);
|
+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)
|
+static int blk_call_notifier_add(struct device *dev)
|
||||||
+{
|
+{
|
||||||
+ struct blk_device_list *new_blkdev;
|
+ struct blk_device_list *new_blkdev;
|
||||||
|
+ struct blk_notify_event *ev;
|
||||||
+
|
+
|
||||||
+ new_blkdev = kmalloc(sizeof(*new_blkdev), GFP_KERNEL);
|
+ new_blkdev = kmalloc(sizeof (*new_blkdev), GFP_KERNEL);
|
||||||
+ if (!new_blkdev)
|
+ if (!new_blkdev)
|
||||||
+ return -ENOMEM;
|
+ return -ENOMEM;
|
||||||
+
|
+
|
||||||
|
+ ev = kmalloc(sizeof(*ev), GFP_KERNEL);
|
||||||
|
+ INIT_DEFERRABLE_WORK(&ev->work, blk_notify_work);
|
||||||
|
+ ev->dev = dev;
|
||||||
+ new_blkdev->dev = dev;
|
+ new_blkdev->dev = dev;
|
||||||
+ mutex_lock(&blk_notifier_lock);
|
+ mutex_lock(&blk_notifier_lock);
|
||||||
+ list_add_tail(&new_blkdev->list, &blk_devices);
|
+ list_add_tail(&new_blkdev->list, &blk_devices);
|
||||||
+ raw_notifier_call_chain(&blk_notifier_list, BLK_DEVICE_ADD, dev);
|
+ schedule_delayed_work(&ev->work, msecs_to_jiffies(500));
|
||||||
+ mutex_unlock(&blk_notifier_lock);
|
+ mutex_unlock(&blk_notifier_lock);
|
||||||
|
+
|
||||||
+ return 0;
|
+ return 0;
|
||||||
+}
|
+}
|
||||||
+
|
+
|
||||||
|
@ -156,19 +149,16 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||||
+device_initcall(blk_notifications_init);
|
+device_initcall(blk_notifications_init);
|
||||||
--- a/include/linux/blkdev.h
|
--- a/include/linux/blkdev.h
|
||||||
+++ b/include/linux/blkdev.h
|
+++ b/include/linux/blkdev.h
|
||||||
@@ -1696,4 +1696,15 @@ static inline bool bdev_can_atomic_write
|
@@ -1696,4 +1696,12 @@ static inline bool bdev_can_atomic_write
|
||||||
|
|
||||||
#define DEFINE_IO_COMP_BATCH(name) struct io_comp_batch name = { }
|
#define DEFINE_IO_COMP_BATCH(name) struct io_comp_batch name = { }
|
||||||
|
|
||||||
+
|
+
|
||||||
|
+#ifdef CONFIG_BLOCK_NOTIFIERS
|
||||||
+#define BLK_DEVICE_ADD 1
|
+#define BLK_DEVICE_ADD 1
|
||||||
+#define BLK_DEVICE_REMOVE 2
|
+#define BLK_DEVICE_REMOVE 2
|
||||||
+#if defined(CONFIG_BLOCK_NOTIFIERS)
|
+extern void blk_register_notify(struct notifier_block *nb);
|
||||||
+void blk_register_notify(struct notifier_block *nb);
|
+extern void blk_unregister_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
|
||||||
+
|
+
|
||||||
#endif /* _LINUX_BLKDEV_H */
|
#endif /* _LINUX_BLKDEV_H */
|
|
@ -0,0 +1,29 @@
|
||||||
|
From 2b28bf485b283991eea9f00c5831c1c39c73991f Mon Sep 17 00:00:00 2001
|
||||||
|
From: Daniel Golle <daniel@makrotopia.org>
|
||||||
|
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 <daniel@makrotopia.org>
|
||||||
|
---
|
||||||
|
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 {
|
|
@ -1,74 +0,0 @@
|
||||||
From f7ec19b34d1b7e934a58ceb102369bbd30b2631d Mon Sep 17 00:00:00 2001
|
|
||||||
From: Daniel Golle <daniel@makrotopia.org>
|
|
||||||
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 <daniel@makrotopia.org>
|
|
||||||
---
|
|
||||||
.../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>;
|
|
||||||
+ };
|
|
||||||
+ };
|
|
||||||
+ };
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
From 043c4f88476cc0f29c9bf82a8a516f58d848e1cd Mon Sep 17 00:00:00 2001
|
|
||||||
From: Daniel Golle <daniel@makrotopia.org>
|
|
||||||
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 <daniel@makrotopia.org>
|
|
||||||
---
|
|
||||||
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);
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
From 9703951cdfe868b130e64d6122420396c2807be8 Mon Sep 17 00:00:00 2001
|
From 26ae98bf77fdbd60536fe5c2175e528469b9ac9a Mon Sep 17 00:00:00 2001
|
||||||
From: Daniel Golle <daniel@makrotopia.org>
|
From: Daniel Golle <daniel@makrotopia.org>
|
||||||
Date: Thu, 30 May 2024 03:15:02 +0100
|
Date: Wed, 15 May 2024 18:18:37 +0300
|
||||||
Subject: [PATCH 5/9] nvmem: implement block NVMEM provider
|
Subject: [PATCH 7/8] nvmem: implement block NVMEM provider
|
||||||
|
|
||||||
On embedded devices using an eMMC it is common that one or more partitions
|
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
|
on the eMMC are used to store MAC addresses and Wi-Fi calibration EEPROM
|
||||||
|
@ -12,8 +12,8 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||||
---
|
---
|
||||||
drivers/nvmem/Kconfig | 11 +++
|
drivers/nvmem/Kconfig | 11 +++
|
||||||
drivers/nvmem/Makefile | 2 +
|
drivers/nvmem/Makefile | 2 +
|
||||||
drivers/nvmem/block.c | 197 +++++++++++++++++++++++++++++++++++++++++
|
drivers/nvmem/block.c | 198 +++++++++++++++++++++++++++++++++++++++++
|
||||||
3 files changed, 210 insertions(+)
|
3 files changed, 211 insertions(+)
|
||||||
create mode 100644 drivers/nvmem/block.c
|
create mode 100644 drivers/nvmem/block.c
|
||||||
|
|
||||||
--- a/drivers/nvmem/Kconfig
|
--- a/drivers/nvmem/Kconfig
|
||||||
|
@ -49,7 +49,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||||
obj-$(CONFIG_NVMEM_IMX_IIM) += nvmem-imx-iim.o
|
obj-$(CONFIG_NVMEM_IMX_IIM) += nvmem-imx-iim.o
|
||||||
--- /dev/null
|
--- /dev/null
|
||||||
+++ b/drivers/nvmem/block.c
|
+++ b/drivers/nvmem/block.c
|
||||||
@@ -0,0 +1,208 @@
|
@@ -0,0 +1,198 @@
|
||||||
+// SPDX-License-Identifier: GPL-2.0-or-later
|
+// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
+/*
|
+/*
|
||||||
+ * block device NVMEM provider
|
+ * block device NVMEM provider
|
||||||
|
@ -72,42 +72,32 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||||
+
|
+
|
||||||
+struct blk_nvmem {
|
+struct blk_nvmem {
|
||||||
+ struct nvmem_device *nvmem;
|
+ struct nvmem_device *nvmem;
|
||||||
+ struct block_device *bdev;
|
+ struct device *dev;
|
||||||
+ struct list_head list;
|
+ struct list_head list;
|
||||||
+};
|
+};
|
||||||
+
|
+
|
||||||
+static int blk_nvmem_reg_read(void *priv, unsigned int from,
|
+static int blk_nvmem_reg_read(void *priv, unsigned int from,
|
||||||
+ void *val, size_t bytes)
|
+ void *val, size_t bytes)
|
||||||
+{
|
+{
|
||||||
|
+ blk_mode_t mode = BLK_OPEN_READ | BLK_OPEN_RESTRICT_WRITES;
|
||||||
+ unsigned long offs = from & ~PAGE_MASK, to_read;
|
+ unsigned long offs = from & ~PAGE_MASK, to_read;
|
||||||
+ pgoff_t f_index = from >> PAGE_SHIFT;
|
+ pgoff_t f_index = from >> PAGE_SHIFT;
|
||||||
+ struct address_space *mapping;
|
|
||||||
+ struct blk_nvmem *bnv = priv;
|
+ struct blk_nvmem *bnv = priv;
|
||||||
+ size_t bytes_left = bytes;
|
+ size_t bytes_left = bytes;
|
||||||
|
+ struct file *bdev_file;
|
||||||
+ struct folio *folio;
|
+ struct folio *folio;
|
||||||
+ void *p;
|
+ void *p;
|
||||||
+ int ret;
|
+ int ret = 0;
|
||||||
+
|
+
|
||||||
+ if (!bnv->bdev)
|
+ bdev_file = bdev_file_open_by_dev(bnv->dev->devt, mode, priv, NULL);
|
||||||
|
+ if (!bdev_file)
|
||||||
+ return -ENODEV;
|
+ return -ENODEV;
|
||||||
+
|
+
|
||||||
+ if (!bnv->bdev->bd_disk)
|
+ if (IS_ERR(bdev_file))
|
||||||
+ return -EINVAL;
|
+ return PTR_ERR(bdev_file);
|
||||||
+
|
|
||||||
+ 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) {
|
+ while (bytes_left) {
|
||||||
+ folio = read_mapping_folio(mapping, f_index++, NULL);
|
+ folio = read_mapping_folio(bdev_file->f_mapping, f_index++, NULL);
|
||||||
+ if (IS_ERR(folio)) {
|
+ if (IS_ERR(folio)) {
|
||||||
+ ret = PTR_ERR(folio);
|
+ ret = PTR_ERR(folio);
|
||||||
+ goto err_release_bdev;
|
+ goto err_release_bdev;
|
||||||
|
@ -122,15 +112,15 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+err_release_bdev:
|
+err_release_bdev:
|
||||||
+ bnv->bdev->bd_disk->fops->release(bnv->bdev->bd_disk);
|
+ fput(bdev_file);
|
||||||
+
|
+
|
||||||
+ return ret;
|
+ return ret;
|
||||||
+}
|
+}
|
||||||
+
|
+
|
||||||
+static int blk_nvmem_register(struct device *dev)
|
+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 block_device *bdev = dev_to_bdev(dev);
|
||||||
|
+ struct device_node *np = dev_of_node(dev);
|
||||||
+ struct nvmem_config config = {};
|
+ struct nvmem_config config = {};
|
||||||
+ struct blk_nvmem *bnv;
|
+ struct blk_nvmem *bnv;
|
||||||
+
|
+
|
||||||
|
@ -178,7 +168,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||||
+ config.ignore_wp = true;
|
+ config.ignore_wp = true;
|
||||||
+ config.of_node = to_of_node(dev->fwnode);
|
+ config.of_node = to_of_node(dev->fwnode);
|
||||||
+
|
+
|
||||||
+ bnv->bdev = bdev;
|
+ bnv->dev = &bdev->bd_device;
|
||||||
+ bnv->nvmem = nvmem_register(&config);
|
+ bnv->nvmem = nvmem_register(&config);
|
||||||
+ if (IS_ERR(bnv->nvmem)) {
|
+ if (IS_ERR(bnv->nvmem)) {
|
||||||
+ dev_err_probe(&bdev->bd_device, PTR_ERR(bnv->nvmem),
|
+ dev_err_probe(&bdev->bd_device, PTR_ERR(bnv->nvmem),
|
||||||
|
@ -197,12 +187,11 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||||
+
|
+
|
||||||
+static void blk_nvmem_unregister(struct device *dev)
|
+static void blk_nvmem_unregister(struct device *dev)
|
||||||
+{
|
+{
|
||||||
+ struct block_device *bdev = dev_to_bdev(dev);
|
|
||||||
+ struct blk_nvmem *bnv_c, *bnv = NULL;
|
+ struct blk_nvmem *bnv_c, *bnv = NULL;
|
||||||
+
|
+
|
||||||
+ mutex_lock(&devices_mutex);
|
+ mutex_lock(&devices_mutex);
|
||||||
+ list_for_each_entry(bnv_c, &nvmem_devices, list) {
|
+ list_for_each_entry(bnv_c, &nvmem_devices, list) {
|
||||||
+ if (bnv_c->bdev == bdev) {
|
+ if (bnv_c->dev == dev) {
|
||||||
+ bnv = bnv_c;
|
+ bnv = bnv_c;
|
||||||
+ break;
|
+ break;
|
||||||
+ }
|
+ }
|
||||||
|
@ -226,6 +215,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||||
+ switch (code) {
|
+ switch (code) {
|
||||||
+ case BLK_DEVICE_ADD:
|
+ case BLK_DEVICE_ADD:
|
||||||
+ return blk_nvmem_register(dev);
|
+ return blk_nvmem_register(dev);
|
||||||
|
+ break;
|
||||||
+ case BLK_DEVICE_REMOVE:
|
+ case BLK_DEVICE_REMOVE:
|
||||||
+ blk_nvmem_unregister(dev);
|
+ blk_nvmem_unregister(dev);
|
||||||
+ break;
|
+ break;
|
|
@ -1,7 +1,7 @@
|
||||||
From 7903b50441000365a6fe5badb39735889f562252 Mon Sep 17 00:00:00 2001
|
From caac69565748349a3e532130a891e18dd5c36c5e Mon Sep 17 00:00:00 2001
|
||||||
From: Daniel Golle <daniel@makrotopia.org>
|
From: Daniel Golle <daniel@makrotopia.org>
|
||||||
Date: Thu, 30 May 2024 03:15:46 +0100
|
Date: Thu, 20 Jul 2023 17:36:44 +0100
|
||||||
Subject: [PATCH 9/9] mmc: block: set GENHD_FL_NVMEM
|
Subject: [PATCH 8/8] mmc: block: set GENHD_FL_NVMEM
|
||||||
|
|
||||||
Set flag to consider MMC block devices as NVMEM providers.
|
Set flag to consider MMC block devices as NVMEM providers.
|
||||||
|
|
|
@ -1,27 +0,0 @@
|
||||||
From ef3e38fec26901b71975d7e810a2df6b8bd54a8e Mon Sep 17 00:00:00 2001
|
|
||||||
From: Daniel Golle <daniel@makrotopia.org>
|
|
||||||
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 <daniel@makrotopia.org>
|
|
||||||
---
|
|
||||||
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)
|
|
Loading…
Reference in a new issue