block: preparations for NVMEM provider
Subsystems (3)
v3 cover block: preparations for NVMEM provider
On embedded devices using an eMMC it is common that one or more (hw/sw) partitions on the eMMC are used to store MAC addresses and Wi-Fi calibration EEPROM data.
Typically the NVMEM framework is used to have kernel drivers read and use binary data from EEPROMs, efuses, flash memory (MTD), ...
Using references to NVMEM bits in Device Tree allows the kernel to access and apply e.g. the Ethernet MAC address, which can be a requirement for userland to come up (e.g. for nfsroot).
The goal of this series is to prepare the block subsystem to allow for the implementation of an NVMEM provider similar to other types of non-volatile storage, so the same approach already used for EEPROMs, MTD (raw flashes) and UBI-managed NAND can also be used for devices storing those bits on an eMMC.
Define a device tree schema for block devices and partitions on them, which (similar to how it now works also for UBI volumes) can be matched by one or more properties.
Also add a simple notification API for other subsystems to be notified about additions and removals of block devices, which is going to be used by the block-backed NVMEM provider.
Overall, this enables uniform handling across practially all flash storage types used for this purpose (MTD, UBI, and soon also MMC or and in future maybe also other block devices).
---
Changes since v2 sent on May 30th 2024 [1] addressing comments from Hauke Mehrtens (https://patchwork.kernel.org/comment/25892133/)
- Check length of UUID and PARTNAME.
- Remove forgotten fallback to get 'partitions' subnode from parent. It is no longer needed and was a left over from earlier development.
- Split series into 3 parts, one for each affected subsystem. This is the first part covering only the changes needed in the block subsystem. The second part adds the actual nvmem provider to drivers/nvmem/, the third part is going to make use of it for MMC block devices and cover changes in drivers/mmc.
Changes since v1 sent on March 21st 2024 [2]:
- introduce notifications for block device addition and removal for in-kernel users. This allows the nvmem driver to be built as a module and avoids using class_interface and block subsystem internals as suggested in https://patchwork.kernel.org/comment/25771998/ and
https://patchwork.kernel.org/comment/25770441/
This series has previously been submitted as RFC on July 19th 2023[3] and most of the basic idea did not change since. Another round of RFC was submitted on March 5th 2024[4].
[1]: https://patchwork.kernel.org/project/linux-block/list/?series=857192
[2]: https://patchwork.kernel.org/project/linux-block/list/?series=837150&archive=both
[3]: https://patchwork.kernel.org/project/linux-block/list/?series=767565
[4]: https://patchwork.kernel.org/project/linux-block/list/?series=832705
Daniel Golle (4):
dt-bindings: block: add basic bindings for block devices
block: partitions: populate fwnode
block: add support for notifications
block: add new genhd flag GENHD_FL_NVMEM
.../bindings/block/block-device.yaml | 22 +++++ .../devicetree/bindings/block/partition.yaml | 51 +++++++++++ .../devicetree/bindings/block/partitions.yaml | 20 +++++ block/Kconfig | 6 ++ block/Makefile | 1 + block/blk-notify.c | 88 +++++++++++++++++++ block/partitions/core.c | 40 +++++++++ include/linux/blkdev.h | 10 +++ 8 files changed, 238 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 create mode 100644 block/blk-notify.c
Signature · 1 line
2.45.2
PATCH v3 1/4 dt-bindings: block: add basic bindings for block devices
Add bindings for block devices which are used to allow referencing nvmem bits on them.
--- .../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
Documentation/devicetree/bindings/block/block-device.yaml new file +22 -0
@@ -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
Documentation/devicetree/bindings/block/partition.yaml new file +51 -0
51 lines not on this page · raw message
Documentation/devicetree/bindings/block/partitions.yaml new file +20 -0
@@ -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
Signature · 1 line
2.45.2
PATCH v3 2/4 block: partitions: populate fwnode
In reply to Daniel GolleLet block partitions to be represented by a firmware node and hence allow them to being referenced e.g. for use with blk-nvmem.
--- block/partitions/core.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+)
block/partitions/core.c +40 -0
@@ -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 *) = {
@@ -281,6 +283,42 @@ static ssize_t whole_disk_show(struct device *dev, } static const DEVICE_ATTR(whole_disk, 0444, whole_disk_show, NULL); +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; + + fw_parts =device_get_named_child_node (ddev,"partitions" ); +if (!fw_parts) + fw_parts =device_get_named_child_node (ddev->parent,"partitions" ); + +if (!fw_parts) +return NULL ; + +fwnode_for_each_child_node (fw_parts, fw_part) { +if (!fwnode_property_read_string (fw_part,"uuid" , &uuid) && + (!bdev->bd_meta_info ||strlen (uuid) >PARTITION_META_INFO_UUIDLTH || +strncmp (uuid, bdev->bd_meta_info->uuid,PARTITION_META_INFO_UUIDLTH ))) +continue ; + +if (!fwnode_property_read_string (fw_part,"partname" , &partname) && + (!bdev->bd_meta_info ||strlen (uuid) >PARTITION_META_INFO_VOLNAMELTH || +strncmp (partname, bdev->bd_meta_info->volname, +PARTITION_META_INFO_VOLNAMELTH ))) +continue ; + +if (!fwnode_property_read_u32 (fw_part,"partno" , &partno) && +bdev_partno (bdev) != 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.
@@ -355,6 +393,8 @@ static struct block_device *add_partition(struct gendisk *disk, int partno, 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);
Signature · 1 line
2.45.2
Jens Axboe
maintainerRe: [PATCH v3 2/4] block: partitions: populate fwnode
Quoted 20 lines · Daniel Golle
block/partitions/core.c +5
-0@@ -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 *) = {@@ -281,6 +283,42 @@ static ssize_t whole_disk_show(struct device *dev, } static const DEVICE_ATTR(whole_disk, 0444, whole_disk_show, NULL); +static struct fwnode_handle *find_partition_fwnode (struct block_device *bdev) +{ +struct fwnode_handle *fw_parts, *fw_part;
block/partitions/core.c static ssize_t whole_disk_show(struct device *dev, · line 298
Quoted 10 lines
block/partitions/core.c +10
-0+struct device *ddev =disk_to_dev (bdev->bd_disk); +const char *partname, *uuid; +u32 partno; + + fw_parts =device_get_named_child_node (ddev,"partitions" ); +if (!fw_parts) + fw_parts =device_get_named_child_node (ddev->parent,"partitions" ); + +if (!fw_parts) +return NULL ;
That last if check should to inside the previous one.
block/partitions/core.c static ssize_t whole_disk_show(struct device *dev, · line 310
Quoted 11 lines
block/partitions/core.c +11
-0+fwnode_for_each_child_node (fw_parts, fw_part) { +if (!fwnode_property_read_string (fw_part,"uuid" , &uuid) && + (!bdev->bd_meta_info ||strlen (uuid) >PARTITION_META_INFO_UUIDLTH || +strncmp (uuid, bdev->bd_meta_info->uuid,PARTITION_META_INFO_UUIDLTH ))) +continue ; + +if (!fwnode_property_read_string (fw_part,"partname" , &partname) && + (!bdev->bd_meta_info ||strlen (uuid) >PARTITION_META_INFO_VOLNAMELTH || +strncmp (partname, bdev->bd_meta_info->volname, +PARTITION_META_INFO_VOLNAMELTH ))) +continue ;
This is pretty hard to make sense of...
Signature · 1 line
Jens Axboe
Re: [PATCH v3 2/4] block: partitions: populate fwnode
Quoted 18 lines · Jens Axboe
Quoted 17 lines · Daniel Golle
block/partitions/core.c +2
-0@@ -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 *) = {@@ -281,6 +283,42 @@ static ssize_t whole_disk_show(struct device *dev, } static const DEVICE_ATTR(whole_disk, 0444, whole_disk_show, NULL);
Quoted 15 lines
block/partitions/core.c static ssize_t whole_disk_show(struct device *dev, · line 298
Quoted 13 lines
block/partitions/core.c +13
-0+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; + + fw_parts =device_get_named_child_node (ddev,"partitions" ); +if (!fw_parts) + fw_parts =device_get_named_child_node (ddev->parent,"partitions" ); + +if (!fw_parts) +return NULL ;That last if check should to inside the previous one.
Actually the previous one should have been removed entirely. I somehow forgot to 'git add' that change.
Quoted 14 lines
block/partitions/core.c static ssize_t whole_disk_show(struct device *dev, · line 310
Quoted 12 lines
block/partitions/core.c +11
-0+fwnode_for_each_child_node (fw_parts, fw_part) { +if (!fwnode_property_read_string (fw_part,"uuid" , &uuid) && + (!bdev->bd_meta_info ||strlen (uuid) >PARTITION_META_INFO_UUIDLTH || +strncmp (uuid, bdev->bd_meta_info->uuid,PARTITION_META_INFO_UUIDLTH ))) +continue ; + +if (!fwnode_property_read_string (fw_part,"partname" , &partname) && + (!bdev->bd_meta_info ||strlen (uuid) >PARTITION_META_INFO_VOLNAMELTH || +strncmp (partname, bdev->bd_meta_info->volname, +PARTITION_META_INFO_VOLNAMELTH ))) +continue ;This is pretty hard to make sense of...
I'll add comments explaining it. Or should I use another syntax, e.g. several nested if-clauses, instead?
Jens Axboe
maintainerRe: [PATCH v3 2/4] block: partitions: populate fwnode
Quoted 53 lines · Daniel Golle
Quoted 18 lines · Jens Axboe
Quoted 17 lines · Daniel Golle
block/partitions/core.c +2
-0@@ -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 *) = {@@ -281,6 +283,42 @@ static ssize_t whole_disk_show(struct device *dev, } static const DEVICE_ATTR(whole_disk, 0444, whole_disk_show, NULL);Quoted 15 lines
block/partitions/core.c static ssize_t whole_disk_show(struct device *dev, · line 298
Quoted 13 lines
block/partitions/core.c +13
-0+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; + + fw_parts =device_get_named_child_node (ddev,"partitions" ); +if (!fw_parts) + fw_parts =device_get_named_child_node (ddev->parent,"partitions" ); + +if (!fw_parts) +return NULL ;That last if check should to inside the previous one.
Actually the previous one should have been removed entirely. I somehow forgot to 'git add' that change.
Quoted 14 lines
block/partitions/core.c static ssize_t whole_disk_show(struct device *dev, · line 310
Quoted 12 lines
block/partitions/core.c +11
-0+fwnode_for_each_child_node (fw_parts, fw_part) { +if (!fwnode_property_read_string (fw_part,"uuid" , &uuid) && + (!bdev->bd_meta_info ||strlen (uuid) >PARTITION_META_INFO_UUIDLTH || +strncmp (uuid, bdev->bd_meta_info->uuid,PARTITION_META_INFO_UUIDLTH ))) +continue ; + +if (!fwnode_property_read_string (fw_part,"partname" , &partname) && + (!bdev->bd_meta_info ||strlen (uuid) >PARTITION_META_INFO_VOLNAMELTH || +strncmp (partname, bdev->bd_meta_info->volname, +PARTITION_META_INFO_VOLNAMELTH ))) +continue ;This is pretty hard to make sense of...
Quoted 2 lines
I'll add comments explaining it. Or should I use another syntax, e.g. several nested if-clauses, instead?
Maybe some kind of helpers for these instead, with comments? Nobody can read the above.
Signature · 1 line
Jens Axboe
PATCH v3 3/4 block: add support for notifications
In reply to Daniel GolleAdd notifier block to notify other subsystems about the addition or removal of block devices.
--- block/Kconfig | 6 +++ block/Makefile | 1 + block/blk-notify.c | 88 ++++++++++++++++++++++++++++++++++++++++++ include/linux/blkdev.h | 8 ++++ 4 files changed, 103 insertions(+) create mode 100644 block/blk-notify.c
block/Kconfig +6 -0
@@ -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
block/Makefile +1 -0
@@ -38,3 +38,4 @@ obj-$(CONFIG_BLK_INLINE_ENCRYPTION) += blk-crypto.o blk-crypto-profile.o \ 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
block/blk-notify.c new file +88 -0
88 lines not on this page · raw message
include/linux/blkdev.h +8 -0
@@ -1687,4 +1687,12 @@ static inline bool bdev_can_atomic_write(struct block_device *bdev)#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 +void blk_register_notify (struct notifier_block *nb); +void blk_unregister_notify (struct notifier_block *nb); +#endif +#endif /* _LINUX_BLKDEV_H */
Signature · 1 line
2.45.2
Jens Axboe
maintainerRe: [PATCH v3 3/4] block: add support for notifications
Quoted 6 lines · Daniel Golle
block/blk-notify.c new file +6
-0+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)
block/blk-notify.c line 60
Quoted 10 lines
block/blk-notify.c new file +10
-0+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 ; +}
Nit: redundant newline.
include/linux/blkdev.h static inline bool bdev_can_atomic_write(struct block_device *bdev) · line 1691
Quoted 11 lines
block/blk-notify.c new file +1
-0+device_initcall (blk_notifications_init);include/linux/blkdev.h +2
-0@@ -1687,4 +1687,12 @@ static inline bool bdev_can_atomic_write(struct block_device *bdev)#define DEFINE_IO_COMP_BATCH (name) struct io_comp_batch name = { } + +#ifdef CONFIG_BLOCK_NOTIFIERS
#if defined(CONFIG_BLOCK_NOTIFIERS)
include/linux/blkdev.h static inline bool bdev_can_atomic_write(struct block_device *bdev) · line 1696
Quoted 5 lines
include/linux/blkdev.h +5
-0+#define BLK_DEVICE_ADD 1 +#define BLK_DEVICE_REMOVE 2 +void blk_register_notify (struct notifier_block *nb); +void blk_unregister_notify (struct notifier_block *nb); +#endif
Surely these helpers should have a !CONFIG_BLOCK_NOTIFIERS failure case definition? Either that, or dummies. As it stands, any caller would need to check if it's enabled or not.
Signature · 1 line
Jens Axboe
Re: [PATCH v3 3/4] block: add support for notifications
Hi Jens,
thanks a lot for the review!
Quoted 11 lines · Jens Axboe
Quoted 10 lines · Daniel Golle
block/blk-notify.c new file +10
-0+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);
Quoted 8 lines
block/blk-notify.c line 60
Quoted 6 lines
block/blk-notify.c new file +6
-0+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 ; +}Nit: redundant newline.
I'll remove the newline before the 'return' statement then, right?
Quoted 15 lines
include/linux/blkdev.h static inline bool bdev_can_atomic_write(struct block_device *bdev) · line 1691
Quoted 12 lines
block/blk-notify.c new file +1
-0+device_initcall (blk_notifications_init);include/linux/blkdev.h +2
-0@@ -1687,4 +1687,12 @@ static inline bool bdev_can_atomic_write(struct block_device *bdev)#define DEFINE_IO_COMP_BATCH (name) struct io_comp_batch name = { } + +#ifdef CONFIG_BLOCK_NOTIFIERS #if
defined(CONFIG_BLOCK_NOTIFIERS)
Quoted 9 lines
include/linux/blkdev.h static inline bool bdev_can_atomic_write(struct block_device *bdev) · line 1696
Quoted 5 lines
include/linux/blkdev.h +5
-0+#define BLK_DEVICE_ADD 1 +#define BLK_DEVICE_REMOVE 2 +void blk_register_notify (struct notifier_block *nb); +void blk_unregister_notify (struct notifier_block *nb); +#endif Surely these helpers should have a !CONFIG_BLOCK_NOTIFIERS failure case definition? Either that, or dummies. As it stands, any caller would need to check if it's enabled or not.
Makes sense. I'll add dummies to the header and always define the macros for notification types.
Note that what I'm planning to do is to have the block nvmem provider select CONFIG_BLOCK_NOTIFIERS in Kconfig, as without that it simply won't work at all.
Cheers
Daniel
Jens Axboe
maintainerRe: [PATCH v3 3/4] block: add support for notifications
Quoted 25 lines · Daniel Golle
Hi Jens,
thanks a lot for the review!
Quoted 11 lines · Jens Axboe
Quoted 10 lines · Daniel Golle
block/blk-notify.c new file +10
-0+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);Quoted 8 lines
block/blk-notify.c line 60
Quoted 6 lines
block/blk-notify.c new file +6
-0+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 ; +}Nit: redundant newline.
Quoted 1 line
I'll remove the newline before the 'return' statement then, right?
Yup
Quoted 24 lines
Quoted 14 lines
include/linux/blkdev.h static inline bool bdev_can_atomic_write(struct block_device *bdev) · line 1691
Quoted 11 lines
block/blk-notify.c new file +1
-0+device_initcall (blk_notifications_init);include/linux/blkdev.h +2
-0@@ -1687,4 +1687,12 @@ static inline bool bdev_can_atomic_write(struct block_device *bdev)#define DEFINE_IO_COMP_BATCH (name) struct io_comp_batch name = { } + +#ifdef CONFIG_BLOCK_NOTIFIERS #if
defined(CONFIG_BLOCK_NOTIFIERS)Quoted 9 lines
include/linux/blkdev.h static inline bool bdev_can_atomic_write(struct block_device *bdev) · line 1696
Quoted 5 lines
include/linux/blkdev.h +5
-0+#define BLK_DEVICE_ADD 1 +#define BLK_DEVICE_REMOVE 2 +void blk_register_notify (struct notifier_block *nb); +void blk_unregister_notify (struct notifier_block *nb); +#endif Surely these helpers should have a !CONFIG_BLOCK_NOTIFIERS failure case definition? Either that, or dummies. As it stands, any caller would need to check if it's enabled or not.
Quoted 2 lines
Makes sense. I'll add dummies to the header and always define the macros for notification types.
Exactly
Quoted 3 lines
Note that what I'm planning to do is to have the block nvmem provider select
CONFIG_BLOCK_NOTIFIERSinKconfig, as without that it simply won't work at all.
Right, but then someone else uses them for something else, and then we'll need it anyway.
Signature · 1 line
Jens Axboe
PATCH v3 4/4 block: add new genhd flag GENHD_FL_NVMEM
In reply to Daniel GolleAdd new flag to destinguish block devices which may act as an NVMEM provider.
--- include/linux/blkdev.h | 2 ++ 1 file changed, 2 insertions(+)
include/linux/blkdev.h +2 -0
@@ -81,11 +81,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 {
Signature · 1 line
2.45.2