All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v5 0/7] I2C IRQ Probe Improvements
From: Charles Keepax @ 2019-06-20 13:34 UTC (permalink / raw)
  To: wsa, mika.westerberg
  Cc: jarkko.nikula, andriy.shevchenko, linux-i2c, linux-acpi,
	linux-kernel, benjamin.tissoires, jbroadus, patches

This series attempts to align as much IRQ handling into the
probe path as possible. Note that I don't have a great setup
for testing these patches so they are mostly just build tested
and need careful review and testing before any of them are
merged.

The series brings the ACPI path inline with the way the device
tree path handles the IRQ entirely at probe time. However,
it still leaves any IRQ specified through the board_info as
being handled at device time. In that case we need to cache
something from the board_info until probe time, which leaves
any alternative solution with something basically the same as
the current handling although perhaps caching more stuff.

Thanks,
Charles

See previous discussions:
 - https://lkml.org/lkml/2019/2/15/989
 - https://www.spinics.net/lists/linux-i2c/msg39541.html

Charles Keepax (7):
  i2c: core: Allow whole core to use i2c_dev_irq_from_resources
  i2c: acpi: Use available IRQ helper functions
  i2c: acpi: Factor out getting the IRQ from ACPI
  i2c: core: Make i2c_acpi_get_irq available to the rest of the I2C core
  i2c: core: Move ACPI IRQ handling to probe time
  i2c: core: Move ACPI gpio IRQ handling into i2c_acpi_get_irq
  i2c: core: Tidy up handling of init_irq

 drivers/i2c/i2c-core-acpi.c | 57 +++++++++++++++++++++++++++++++--------------
 drivers/i2c/i2c-core-base.c | 11 +++++----
 drivers/i2c/i2c-core.h      | 11 +++++++++
 3 files changed, 57 insertions(+), 22 deletions(-)

-- 
2.11.0


^ permalink raw reply

* [PATCH v5 7/7] i2c: core: Tidy up handling of init_irq
From: Charles Keepax @ 2019-06-20 13:34 UTC (permalink / raw)
  To: wsa, mika.westerberg
  Cc: jarkko.nikula, andriy.shevchenko, linux-i2c, linux-acpi,
	linux-kernel, benjamin.tissoires, jbroadus, patches
In-Reply-To: <20190620133420.4632-1-ckeepax@opensource.cirrus.com>

Only set init_irq during i2c_device_new and only handle client->irq on
the probe/remove paths.

Suggested-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
---

No changes since v4.

Thanks,
Charles

 drivers/i2c/i2c-core-base.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c
index 95a0380286c1c..a3dbaefe4ca66 100644
--- a/drivers/i2c/i2c-core-base.c
+++ b/drivers/i2c/i2c-core-base.c
@@ -314,6 +314,8 @@ static int i2c_device_probe(struct device *dev)
 
 	driver = to_i2c_driver(dev->driver);
 
+	client->irq = client->init_irq;
+
 	if (!client->irq && !driver->disable_i2c_core_irq_mapping) {
 		int irq = -ENOENT;
 
@@ -424,7 +426,7 @@ static int i2c_device_remove(struct device *dev)
 	dev_pm_clear_wake_irq(&client->dev);
 	device_init_wakeup(&client->dev, false);
 
-	client->irq = client->init_irq;
+	client->irq = 0;
 	if (client->flags & I2C_CLIENT_HOST_NOTIFY)
 		pm_runtime_put(&client->adapter->dev);
 
@@ -741,7 +743,6 @@ i2c_new_client_device(struct i2c_adapter *adap, struct i2c_board_info const *inf
 	if (!client->init_irq)
 		client->init_irq = i2c_dev_irq_from_resources(info->resources,
 							 info->num_resources);
-	client->irq = client->init_irq;
 
 	strlcpy(client->name, info->type, sizeof(client->name));
 
-- 
2.11.0


^ permalink raw reply related

* [PATCH v5 3/7] i2c: acpi: Factor out getting the IRQ from ACPI
From: Charles Keepax @ 2019-06-20 13:34 UTC (permalink / raw)
  To: wsa, mika.westerberg
  Cc: jarkko.nikula, andriy.shevchenko, linux-i2c, linux-acpi,
	linux-kernel, benjamin.tissoires, jbroadus, patches
In-Reply-To: <20190620133420.4632-1-ckeepax@opensource.cirrus.com>

In preparation for future refactoring factor out the fetch of the IRQ
into its own helper function.

Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
---

No changes since v4.

Thanks,
Charles

 drivers/i2c/i2c-core-acpi.c | 33 +++++++++++++++++++++------------
 1 file changed, 21 insertions(+), 12 deletions(-)

diff --git a/drivers/i2c/i2c-core-acpi.c b/drivers/i2c/i2c-core-acpi.c
index 47d5b1c5ec9e0..7d4d66ba752d4 100644
--- a/drivers/i2c/i2c-core-acpi.c
+++ b/drivers/i2c/i2c-core-acpi.c
@@ -144,14 +144,30 @@ static int i2c_acpi_add_resource(struct acpi_resource *ares, void *data)
 	return 1; /* No need to add resource to the list */
 }
 
+static int i2c_acpi_get_irq(struct acpi_device *adev)
+{
+	struct list_head resource_list;
+	int irq = -ENOENT;
+	int ret;
+
+	INIT_LIST_HEAD(&resource_list);
+
+	ret = acpi_dev_get_resources(adev, &resource_list,
+				     i2c_acpi_add_resource, &irq);
+	if (ret < 0)
+		return -EINVAL;
+
+	acpi_dev_free_resource_list(&resource_list);
+
+	return irq;
+}
+
 static int i2c_acpi_get_info(struct acpi_device *adev,
 			     struct i2c_board_info *info,
 			     struct i2c_adapter *adapter,
 			     acpi_handle *adapter_handle)
 {
-	struct list_head resource_list;
 	struct i2c_acpi_lookup lookup;
-	int irq = -ENOENT;
 	int ret;
 
 	memset(&lookup, 0, sizeof(lookup));
@@ -182,16 +198,9 @@ static int i2c_acpi_get_info(struct acpi_device *adev,
 		*adapter_handle = lookup.adapter_handle;
 
 	/* Then fill IRQ number if any */
-	INIT_LIST_HEAD(&resource_list);
-	ret = acpi_dev_get_resources(adev, &resource_list,
-				     i2c_acpi_add_resource, &irq);
-	if (ret < 0)
-		return -EINVAL;
-
-	if (irq > 0)
-		info->irq = irq;
-
-	acpi_dev_free_resource_list(&resource_list);
+	ret = i2c_acpi_get_irq(adev);
+	if (ret > 0)
+		info->irq = ret;
 
 	acpi_set_modalias(adev, dev_name(&adev->dev), info->type,
 			  sizeof(info->type));
-- 
2.11.0


^ permalink raw reply related

* [PATCH v5 1/7] i2c: core: Allow whole core to use i2c_dev_irq_from_resources
From: Charles Keepax @ 2019-06-20 13:34 UTC (permalink / raw)
  To: wsa, mika.westerberg
  Cc: jarkko.nikula, andriy.shevchenko, linux-i2c, linux-acpi,
	linux-kernel, benjamin.tissoires, jbroadus, patches
In-Reply-To: <20190620133420.4632-1-ckeepax@opensource.cirrus.com>

Remove the static from i2c_dev_irq_from _resources so that other parts
of the core code can use this helper function.

Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
---

No changes since v4.

Thanks,
Charles

 drivers/i2c/i2c-core-base.c | 4 ++--
 drivers/i2c/i2c-core.h      | 2 ++
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c
index 2569e97f9bf35..8a303246d534b 100644
--- a/drivers/i2c/i2c-core-base.c
+++ b/drivers/i2c/i2c-core-base.c
@@ -679,8 +679,8 @@ static void i2c_dev_set_name(struct i2c_adapter *adap,
 		     i2c_encode_flags_to_addr(client));
 }
 
-static int i2c_dev_irq_from_resources(const struct resource *resources,
-				      unsigned int num_resources)
+int i2c_dev_irq_from_resources(const struct resource *resources,
+			       unsigned int num_resources)
 {
 	struct irq_data *irqd;
 	int i;
diff --git a/drivers/i2c/i2c-core.h b/drivers/i2c/i2c-core.h
index 851c11b4c0f3a..2a3b28bf826b1 100644
--- a/drivers/i2c/i2c-core.h
+++ b/drivers/i2c/i2c-core.h
@@ -19,6 +19,8 @@ extern struct list_head	__i2c_board_list;
 extern int		__i2c_first_dynamic_bus_num;
 
 int i2c_check_7bit_addr_validity_strict(unsigned short addr);
+int i2c_dev_irq_from_resources(const struct resource *resources,
+			       unsigned int num_resources);
 
 /*
  * We only allow atomic transfers for very late communication, e.g. to send
-- 
2.11.0


^ permalink raw reply related

* Re: [PATCH v2 1/4] vfs: create a generic checking function for FS_IOC_SETFLAGS
From: Jan Kara @ 2019-06-20 13:34 UTC (permalink / raw)
  To: Darrick J. Wong
  Cc: shaggy, jfs-discussion, linux-efi, linux-btrfs, yuchao0, clm,
	adilger.kernel, matthew.garrett, linux-nilfs, cluster-devel,
	linux-ext4, josef, reiserfs-devel, viro, dsterba, jaegeuk, tytso,
	ard.biesheuvel, linux-kernel, linux-f2fs-devel, linux-xfs, jk,
	jack, linux-fsdevel, linux-mtd, ocfs2-devel
In-Reply-To: <20190612004258.GX1871505@magnolia>

On Tue 11-06-19 17:42:58, Darrick J. Wong wrote:
> From: Darrick J. Wong <darrick.wong@oracle.com>
> 
> Create a generic checking function for the incoming FS_IOC_SETFLAGS flag
> values so that we can standardize the implementations that follow ext4's
> flag values.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>

The patch looks good to me. You can add:

Reviewed-by: Jan Kara <jack@suse.cz>

								Honza

> ---
> v2: fix jfs locking and remove its opencoded flags check
> ---
>  fs/btrfs/ioctl.c    |   13 +++++--------
>  fs/efivarfs/file.c  |   18 +++++++++++++-----
>  fs/ext2/ioctl.c     |   16 ++++------------
>  fs/ext4/ioctl.c     |   13 +++----------
>  fs/f2fs/file.c      |    7 ++++---
>  fs/gfs2/file.c      |   42 +++++++++++++++++++++++++++++-------------
>  fs/hfsplus/ioctl.c  |   21 ++++++++++++---------
>  fs/inode.c          |   17 +++++++++++++++++
>  fs/jfs/ioctl.c      |   22 +++++++---------------
>  fs/nilfs2/ioctl.c   |    9 ++-------
>  fs/ocfs2/ioctl.c    |   13 +++----------
>  fs/reiserfs/ioctl.c |   10 ++++------
>  fs/ubifs/ioctl.c    |   13 +++----------
>  include/linux/fs.h  |    2 ++
>  14 files changed, 108 insertions(+), 108 deletions(-)
> 
> diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
> index 6dafa857bbb9..f408aa93b0cf 100644
> --- a/fs/btrfs/ioctl.c
> +++ b/fs/btrfs/ioctl.c
> @@ -187,7 +187,7 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
>  	struct btrfs_inode *binode = BTRFS_I(inode);
>  	struct btrfs_root *root = binode->root;
>  	struct btrfs_trans_handle *trans;
> -	unsigned int fsflags;
> +	unsigned int fsflags, old_fsflags;
>  	int ret;
>  	const char *comp = NULL;
>  	u32 binode_flags = binode->flags;
> @@ -212,13 +212,10 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
>  	inode_lock(inode);
>  
>  	fsflags = btrfs_mask_fsflags_for_type(inode, fsflags);
> -	if ((fsflags ^ btrfs_inode_flags_to_fsflags(binode->flags)) &
> -	    (FS_APPEND_FL | FS_IMMUTABLE_FL)) {
> -		if (!capable(CAP_LINUX_IMMUTABLE)) {
> -			ret = -EPERM;
> -			goto out_unlock;
> -		}
> -	}
> +	old_fsflags = btrfs_inode_flags_to_fsflags(binode->flags);
> +	ret = vfs_ioc_setflags_check(inode, old_fsflags, fsflags);
> +	if (ret)
> +		goto out_unlock;
>  
>  	if (fsflags & FS_SYNC_FL)
>  		binode_flags |= BTRFS_INODE_SYNC;
> diff --git a/fs/efivarfs/file.c b/fs/efivarfs/file.c
> index 8e568428c88b..f4f6c1bec132 100644
> --- a/fs/efivarfs/file.c
> +++ b/fs/efivarfs/file.c
> @@ -110,16 +110,22 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf,
>  	return size;
>  }
>  
> -static int
> -efivarfs_ioc_getxflags(struct file *file, void __user *arg)
> +static inline unsigned int efivarfs_getflags(struct inode *inode)
>  {
> -	struct inode *inode = file->f_mapping->host;
>  	unsigned int i_flags;
>  	unsigned int flags = 0;
>  
>  	i_flags = inode->i_flags;
>  	if (i_flags & S_IMMUTABLE)
>  		flags |= FS_IMMUTABLE_FL;
> +	return flags;
> +}
> +
> +static int
> +efivarfs_ioc_getxflags(struct file *file, void __user *arg)
> +{
> +	struct inode *inode = file->f_mapping->host;
> +	unsigned int flags = efivarfs_getflags(inode);
>  
>  	if (copy_to_user(arg, &flags, sizeof(flags)))
>  		return -EFAULT;
> @@ -132,6 +138,7 @@ efivarfs_ioc_setxflags(struct file *file, void __user *arg)
>  	struct inode *inode = file->f_mapping->host;
>  	unsigned int flags;
>  	unsigned int i_flags = 0;
> +	unsigned int oldflags = efivarfs_getflags(inode);
>  	int error;
>  
>  	if (!inode_owner_or_capable(inode))
> @@ -143,8 +150,9 @@ efivarfs_ioc_setxflags(struct file *file, void __user *arg)
>  	if (flags & ~FS_IMMUTABLE_FL)
>  		return -EOPNOTSUPP;
>  
> -	if (!capable(CAP_LINUX_IMMUTABLE))
> -		return -EPERM;
> +	error = vfs_ioc_setflags_check(inode, oldflags, flags);
> +	if (error)
> +		return error;
>  
>  	if (flags & FS_IMMUTABLE_FL)
>  		i_flags |= S_IMMUTABLE;
> diff --git a/fs/ext2/ioctl.c b/fs/ext2/ioctl.c
> index 0367c0039e68..88b3b9720023 100644
> --- a/fs/ext2/ioctl.c
> +++ b/fs/ext2/ioctl.c
> @@ -60,18 +60,10 @@ long ext2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
>  		}
>  		oldflags = ei->i_flags;
>  
> -		/*
> -		 * The IMMUTABLE and APPEND_ONLY flags can only be changed by
> -		 * the relevant capability.
> -		 *
> -		 * This test looks nicer. Thanks to Pauline Middelink
> -		 */
> -		if ((flags ^ oldflags) & (EXT2_APPEND_FL | EXT2_IMMUTABLE_FL)) {
> -			if (!capable(CAP_LINUX_IMMUTABLE)) {
> -				inode_unlock(inode);
> -				ret = -EPERM;
> -				goto setflags_out;
> -			}
> +		ret = vfs_ioc_setflags_check(inode, oldflags, flags);
> +		if (ret) {
> +			inode_unlock(inode);
> +			goto setflags_out;
>  		}
>  
>  		flags = flags & EXT2_FL_USER_MODIFIABLE;
> diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
> index e486e49b31ed..5126ee351a84 100644
> --- a/fs/ext4/ioctl.c
> +++ b/fs/ext4/ioctl.c
> @@ -289,16 +289,9 @@ static int ext4_ioctl_setflags(struct inode *inode,
>  	/* The JOURNAL_DATA flag is modifiable only by root */
>  	jflag = flags & EXT4_JOURNAL_DATA_FL;
>  
> -	/*
> -	 * The IMMUTABLE and APPEND_ONLY flags can only be changed by
> -	 * the relevant capability.
> -	 *
> -	 * This test looks nicer. Thanks to Pauline Middelink
> -	 */
> -	if ((flags ^ oldflags) & (EXT4_APPEND_FL | EXT4_IMMUTABLE_FL)) {
> -		if (!capable(CAP_LINUX_IMMUTABLE))
> -			goto flags_out;
> -	}
> +	err = vfs_ioc_setflags_check(inode, oldflags, flags);
> +	if (err)
> +		goto flags_out;
>  
>  	/*
>  	 * The JOURNAL_DATA flag can only be changed by
> diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
> index 45b45f37d347..a969d5497e03 100644
> --- a/fs/f2fs/file.c
> +++ b/fs/f2fs/file.c
> @@ -1670,6 +1670,7 @@ static int __f2fs_ioc_setflags(struct inode *inode, unsigned int flags)
>  {
>  	struct f2fs_inode_info *fi = F2FS_I(inode);
>  	unsigned int oldflags;
> +	int err;
>  
>  	/* Is it quota file? Do not allow user to mess with it */
>  	if (IS_NOQUOTA(inode))
> @@ -1679,9 +1680,9 @@ static int __f2fs_ioc_setflags(struct inode *inode, unsigned int flags)
>  
>  	oldflags = fi->i_flags;
>  
> -	if ((flags ^ oldflags) & (F2FS_APPEND_FL | F2FS_IMMUTABLE_FL))
> -		if (!capable(CAP_LINUX_IMMUTABLE))
> -			return -EPERM;
> +	err = vfs_ioc_setflags_check(inode, oldflags, flags);
> +	if (err)
> +		return err;
>  
>  	flags = flags & F2FS_FL_USER_MODIFIABLE;
>  	flags |= oldflags & ~F2FS_FL_USER_MODIFIABLE;
> diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c
> index d174b1f8fd08..99f53cf699c6 100644
> --- a/fs/gfs2/file.c
> +++ b/fs/gfs2/file.c
> @@ -136,27 +136,36 @@ static struct {
>  	{FS_JOURNAL_DATA_FL, GFS2_DIF_JDATA | GFS2_DIF_INHERIT_JDATA},
>  };
>  
> +static inline u32 gfs2_gfsflags_to_fsflags(struct inode *inode, u32 gfsflags)
> +{
> +	int i;
> +	u32 fsflags = 0;
> +
> +	if (S_ISDIR(inode->i_mode))
> +		gfsflags &= ~GFS2_DIF_JDATA;
> +	else
> +		gfsflags &= ~GFS2_DIF_INHERIT_JDATA;
> +
> +	for (i = 0; i < ARRAY_SIZE(fsflag_gfs2flag); i++)
> +		if (gfsflags & fsflag_gfs2flag[i].gfsflag)
> +			fsflags |= fsflag_gfs2flag[i].fsflag;
> +	return fsflags;
> +}
> +
>  static int gfs2_get_flags(struct file *filp, u32 __user *ptr)
>  {
>  	struct inode *inode = file_inode(filp);
>  	struct gfs2_inode *ip = GFS2_I(inode);
>  	struct gfs2_holder gh;
> -	int i, error;
> -	u32 gfsflags, fsflags = 0;
> +	int error;
> +	u32 fsflags;
>  
>  	gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &gh);
>  	error = gfs2_glock_nq(&gh);
>  	if (error)
>  		goto out_uninit;
>  
> -	gfsflags = ip->i_diskflags;
> -	if (S_ISDIR(inode->i_mode))
> -		gfsflags &= ~GFS2_DIF_JDATA;
> -	else
> -		gfsflags &= ~GFS2_DIF_INHERIT_JDATA;
> -	for (i = 0; i < ARRAY_SIZE(fsflag_gfs2flag); i++)
> -		if (gfsflags & fsflag_gfs2flag[i].gfsflag)
> -			fsflags |= fsflag_gfs2flag[i].fsflag;
> +	fsflags = gfs2_gfsflags_to_fsflags(inode, ip->i_diskflags);
>  
>  	if (put_user(fsflags, ptr))
>  		error = -EFAULT;
> @@ -200,9 +209,11 @@ void gfs2_set_inode_flags(struct inode *inode)
>   * @filp: file pointer
>   * @reqflags: The flags to set
>   * @mask: Indicates which flags are valid
> + * @fsflags: The FS_* inode flags passed in
>   *
>   */
> -static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask)
> +static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask,
> +			     const u32 fsflags)
>  {
>  	struct inode *inode = file_inode(filp);
>  	struct gfs2_inode *ip = GFS2_I(inode);
> @@ -210,7 +221,7 @@ static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask)
>  	struct buffer_head *bh;
>  	struct gfs2_holder gh;
>  	int error;
> -	u32 new_flags, flags;
> +	u32 new_flags, flags, oldflags;
>  
>  	error = mnt_want_write_file(filp);
>  	if (error)
> @@ -220,6 +231,11 @@ static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask)
>  	if (error)
>  		goto out_drop_write;
>  
> +	oldflags = gfs2_gfsflags_to_fsflags(inode, ip->i_diskflags);
> +	error = vfs_ioc_setflags_check(inode, oldflags, fsflags);
> +	if (error)
> +		goto out;
> +
>  	error = -EACCES;
>  	if (!inode_owner_or_capable(inode))
>  		goto out;
> @@ -308,7 +324,7 @@ static int gfs2_set_flags(struct file *filp, u32 __user *ptr)
>  		mask &= ~(GFS2_DIF_TOPDIR | GFS2_DIF_INHERIT_JDATA);
>  	}
>  
> -	return do_gfs2_set_flags(filp, gfsflags, mask);
> +	return do_gfs2_set_flags(filp, gfsflags, mask, fsflags);
>  }
>  
>  static int gfs2_getlabel(struct file *filp, char __user *label)
> diff --git a/fs/hfsplus/ioctl.c b/fs/hfsplus/ioctl.c
> index 5e6502ef7415..862a3c9481d7 100644
> --- a/fs/hfsplus/ioctl.c
> +++ b/fs/hfsplus/ioctl.c
> @@ -57,9 +57,8 @@ static int hfsplus_ioctl_bless(struct file *file, int __user *user_flags)
>  	return 0;
>  }
>  
> -static int hfsplus_ioctl_getflags(struct file *file, int __user *user_flags)
> +static inline unsigned int hfsplus_getflags(struct inode *inode)
>  {
> -	struct inode *inode = file_inode(file);
>  	struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
>  	unsigned int flags = 0;
>  
> @@ -69,6 +68,13 @@ static int hfsplus_ioctl_getflags(struct file *file, int __user *user_flags)
>  		flags |= FS_APPEND_FL;
>  	if (hip->userflags & HFSPLUS_FLG_NODUMP)
>  		flags |= FS_NODUMP_FL;
> +	return flags;
> +}
> +
> +static int hfsplus_ioctl_getflags(struct file *file, int __user *user_flags)
> +{
> +	struct inode *inode = file_inode(file);
> +	unsigned int flags = hfsplus_getflags(inode);
>  
>  	return put_user(flags, user_flags);
>  }
> @@ -78,6 +84,7 @@ static int hfsplus_ioctl_setflags(struct file *file, int __user *user_flags)
>  	struct inode *inode = file_inode(file);
>  	struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
>  	unsigned int flags, new_fl = 0;
> +	unsigned int oldflags = hfsplus_getflags(inode);
>  	int err = 0;
>  
>  	err = mnt_want_write_file(file);
> @@ -96,13 +103,9 @@ static int hfsplus_ioctl_setflags(struct file *file, int __user *user_flags)
>  
>  	inode_lock(inode);
>  
> -	if ((flags & (FS_IMMUTABLE_FL|FS_APPEND_FL)) ||
> -	    inode->i_flags & (S_IMMUTABLE|S_APPEND)) {
> -		if (!capable(CAP_LINUX_IMMUTABLE)) {
> -			err = -EPERM;
> -			goto out_unlock_inode;
> -		}
> -	}
> +	err = vfs_ioc_setflags_check(inode, oldflags, flags);
> +	if (err)
> +		goto out_unlock_inode;
>  
>  	/* don't silently ignore unsupported ext2 flags */
>  	if (flags & ~(FS_IMMUTABLE_FL|FS_APPEND_FL|FS_NODUMP_FL)) {
> diff --git a/fs/inode.c b/fs/inode.c
> index df6542ec3b88..0ce60b720608 100644
> --- a/fs/inode.c
> +++ b/fs/inode.c
> @@ -2170,3 +2170,20 @@ struct timespec64 current_time(struct inode *inode)
>  	return timespec64_trunc(now, inode->i_sb->s_time_gran);
>  }
>  EXPORT_SYMBOL(current_time);
> +
> +/* Generic function to check FS_IOC_SETFLAGS values. */
> +int vfs_ioc_setflags_check(struct inode *inode, int oldflags, int flags)
> +{
> +	/*
> +	 * The IMMUTABLE and APPEND_ONLY flags can only be changed by
> +	 * the relevant capability.
> +	 *
> +	 * This test looks nicer. Thanks to Pauline Middelink
> +	 */
> +	if ((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL) &&
> +	    !capable(CAP_LINUX_IMMUTABLE))
> +		return -EPERM;
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(vfs_ioc_setflags_check);
> diff --git a/fs/jfs/ioctl.c b/fs/jfs/ioctl.c
> index ba34dae8bd9f..b485c2d7620f 100644
> --- a/fs/jfs/ioctl.c
> +++ b/fs/jfs/ioctl.c
> @@ -98,24 +98,16 @@ long jfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
>  		/* Lock against other parallel changes of flags */
>  		inode_lock(inode);
>  
> -		oldflags = jfs_inode->mode2;
> -
> -		/*
> -		 * The IMMUTABLE and APPEND_ONLY flags can only be changed by
> -		 * the relevant capability.
> -		 */
> -		if ((oldflags & JFS_IMMUTABLE_FL) ||
> -			((flags ^ oldflags) &
> -			(JFS_APPEND_FL | JFS_IMMUTABLE_FL))) {
> -			if (!capable(CAP_LINUX_IMMUTABLE)) {
> -				inode_unlock(inode);
> -				err = -EPERM;
> -				goto setflags_out;
> -			}
> +		oldflags = jfs_map_ext2(jfs_inode->mode2 & JFS_FL_USER_VISIBLE,
> +					0);
> +		err = vfs_ioc_setflags_check(inode, oldflags, flags);
> +		if (err) {
> +			inode_unlock(inode);
> +			goto setflags_out;
>  		}
>  
>  		flags = flags & JFS_FL_USER_MODIFIABLE;
> -		flags |= oldflags & ~JFS_FL_USER_MODIFIABLE;
> +		flags |= jfs_inode->mode2 & ~JFS_FL_USER_MODIFIABLE;
>  		jfs_inode->mode2 = flags;
>  
>  		jfs_set_inode_flags(inode);
> diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c
> index 9b96d79eea6c..0632336d2515 100644
> --- a/fs/nilfs2/ioctl.c
> +++ b/fs/nilfs2/ioctl.c
> @@ -148,13 +148,8 @@ static int nilfs_ioctl_setflags(struct inode *inode, struct file *filp,
>  
>  	oldflags = NILFS_I(inode)->i_flags;
>  
> -	/*
> -	 * The IMMUTABLE and APPEND_ONLY flags can only be changed by the
> -	 * relevant capability.
> -	 */
> -	ret = -EPERM;
> -	if (((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL)) &&
> -	    !capable(CAP_LINUX_IMMUTABLE))
> +	ret = vfs_ioc_setflags_check(inode, oldflags, flags);
> +	if (ret)
>  		goto out;
>  
>  	ret = nilfs_transaction_begin(inode->i_sb, &ti, 0);
> diff --git a/fs/ocfs2/ioctl.c b/fs/ocfs2/ioctl.c
> index 994726ada857..467a2faf0305 100644
> --- a/fs/ocfs2/ioctl.c
> +++ b/fs/ocfs2/ioctl.c
> @@ -106,16 +106,9 @@ static int ocfs2_set_inode_attr(struct inode *inode, unsigned flags,
>  	flags = flags & mask;
>  	flags |= oldflags & ~mask;
>  
> -	/*
> -	 * The IMMUTABLE and APPEND_ONLY flags can only be changed by
> -	 * the relevant capability.
> -	 */
> -	status = -EPERM;
> -	if ((oldflags & OCFS2_IMMUTABLE_FL) || ((flags ^ oldflags) &
> -		(OCFS2_APPEND_FL | OCFS2_IMMUTABLE_FL))) {
> -		if (!capable(CAP_LINUX_IMMUTABLE))
> -			goto bail_unlock;
> -	}
> +	status = vfs_ioc_setflags_check(inode, oldflags, flags);
> +	if (status)
> +		goto bail_unlock;
>  
>  	handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);
>  	if (IS_ERR(handle)) {
> diff --git a/fs/reiserfs/ioctl.c b/fs/reiserfs/ioctl.c
> index acbbaf7a0bb2..92bcb1ecd994 100644
> --- a/fs/reiserfs/ioctl.c
> +++ b/fs/reiserfs/ioctl.c
> @@ -74,13 +74,11 @@ long reiserfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
>  				err = -EPERM;
>  				goto setflags_out;
>  			}
> -			if (((flags ^ REISERFS_I(inode)->
> -			      i_attrs) & (REISERFS_IMMUTABLE_FL |
> -					  REISERFS_APPEND_FL))
> -			    && !capable(CAP_LINUX_IMMUTABLE)) {
> -				err = -EPERM;
> +			err = vfs_ioc_setflags_check(inode,
> +						     REISERFS_I(inode)->i_attrs,
> +						     flags);
> +			if (err)
>  				goto setflags_out;
> -			}
>  			if ((flags & REISERFS_NOTAIL_FL) &&
>  			    S_ISREG(inode->i_mode)) {
>  				int result;
> diff --git a/fs/ubifs/ioctl.c b/fs/ubifs/ioctl.c
> index 4f1a397fda69..bdea836fc38b 100644
> --- a/fs/ubifs/ioctl.c
> +++ b/fs/ubifs/ioctl.c
> @@ -107,18 +107,11 @@ static int setflags(struct inode *inode, int flags)
>  	if (err)
>  		return err;
>  
> -	/*
> -	 * The IMMUTABLE and APPEND_ONLY flags can only be changed by
> -	 * the relevant capability.
> -	 */
>  	mutex_lock(&ui->ui_mutex);
>  	oldflags = ubifs2ioctl(ui->flags);
> -	if ((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL)) {
> -		if (!capable(CAP_LINUX_IMMUTABLE)) {
> -			err = -EPERM;
> -			goto out_unlock;
> -		}
> -	}
> +	err = vfs_ioc_setflags_check(inode, oldflags, flags);
> +	if (err)
> +		goto out_unlock;
>  
>  	ui->flags = ioctl2ubifs(flags);
>  	ubifs_set_inode_flags(inode);
> diff --git a/include/linux/fs.h b/include/linux/fs.h
> index f7fdfe93e25d..1825d055808c 100644
> --- a/include/linux/fs.h
> +++ b/include/linux/fs.h
> @@ -3546,4 +3546,6 @@ static inline struct sock *io_uring_get_socket(struct file *file)
>  }
>  #endif
>  
> +int vfs_ioc_setflags_check(struct inode *inode, int oldflags, int flags);
> +
>  #endif /* _LINUX_FS_H */
> 
-- 
Jan Kara <jack@suse.com>
SUSE Labs, CR

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

^ permalink raw reply

* Re: [f2fs-dev] [PATCH v2 1/4] vfs: create a generic checking function for FS_IOC_SETFLAGS
From: Jan Kara @ 2019-06-20 13:34 UTC (permalink / raw)
  To: Darrick J. Wong
  Cc: shaggy, jfs-discussion, linux-efi, linux-btrfs, clm,
	adilger.kernel, matthew.garrett, linux-nilfs, cluster-devel,
	linux-ext4, josef, reiserfs-devel, viro, dsterba, jaegeuk, tytso,
	ard.biesheuvel, linux-kernel, linux-f2fs-devel, linux-xfs, jk,
	jack, linux-fsdevel, linux-mtd, ocfs2-devel
In-Reply-To: <20190612004258.GX1871505@magnolia>

On Tue 11-06-19 17:42:58, Darrick J. Wong wrote:
> From: Darrick J. Wong <darrick.wong@oracle.com>
> 
> Create a generic checking function for the incoming FS_IOC_SETFLAGS flag
> values so that we can standardize the implementations that follow ext4's
> flag values.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>

The patch looks good to me. You can add:

Reviewed-by: Jan Kara <jack@suse.cz>

								Honza

> ---
> v2: fix jfs locking and remove its opencoded flags check
> ---
>  fs/btrfs/ioctl.c    |   13 +++++--------
>  fs/efivarfs/file.c  |   18 +++++++++++++-----
>  fs/ext2/ioctl.c     |   16 ++++------------
>  fs/ext4/ioctl.c     |   13 +++----------
>  fs/f2fs/file.c      |    7 ++++---
>  fs/gfs2/file.c      |   42 +++++++++++++++++++++++++++++-------------
>  fs/hfsplus/ioctl.c  |   21 ++++++++++++---------
>  fs/inode.c          |   17 +++++++++++++++++
>  fs/jfs/ioctl.c      |   22 +++++++---------------
>  fs/nilfs2/ioctl.c   |    9 ++-------
>  fs/ocfs2/ioctl.c    |   13 +++----------
>  fs/reiserfs/ioctl.c |   10 ++++------
>  fs/ubifs/ioctl.c    |   13 +++----------
>  include/linux/fs.h  |    2 ++
>  14 files changed, 108 insertions(+), 108 deletions(-)
> 
> diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
> index 6dafa857bbb9..f408aa93b0cf 100644
> --- a/fs/btrfs/ioctl.c
> +++ b/fs/btrfs/ioctl.c
> @@ -187,7 +187,7 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
>  	struct btrfs_inode *binode = BTRFS_I(inode);
>  	struct btrfs_root *root = binode->root;
>  	struct btrfs_trans_handle *trans;
> -	unsigned int fsflags;
> +	unsigned int fsflags, old_fsflags;
>  	int ret;
>  	const char *comp = NULL;
>  	u32 binode_flags = binode->flags;
> @@ -212,13 +212,10 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
>  	inode_lock(inode);
>  
>  	fsflags = btrfs_mask_fsflags_for_type(inode, fsflags);
> -	if ((fsflags ^ btrfs_inode_flags_to_fsflags(binode->flags)) &
> -	    (FS_APPEND_FL | FS_IMMUTABLE_FL)) {
> -		if (!capable(CAP_LINUX_IMMUTABLE)) {
> -			ret = -EPERM;
> -			goto out_unlock;
> -		}
> -	}
> +	old_fsflags = btrfs_inode_flags_to_fsflags(binode->flags);
> +	ret = vfs_ioc_setflags_check(inode, old_fsflags, fsflags);
> +	if (ret)
> +		goto out_unlock;
>  
>  	if (fsflags & FS_SYNC_FL)
>  		binode_flags |= BTRFS_INODE_SYNC;
> diff --git a/fs/efivarfs/file.c b/fs/efivarfs/file.c
> index 8e568428c88b..f4f6c1bec132 100644
> --- a/fs/efivarfs/file.c
> +++ b/fs/efivarfs/file.c
> @@ -110,16 +110,22 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf,
>  	return size;
>  }
>  
> -static int
> -efivarfs_ioc_getxflags(struct file *file, void __user *arg)
> +static inline unsigned int efivarfs_getflags(struct inode *inode)
>  {
> -	struct inode *inode = file->f_mapping->host;
>  	unsigned int i_flags;
>  	unsigned int flags = 0;
>  
>  	i_flags = inode->i_flags;
>  	if (i_flags & S_IMMUTABLE)
>  		flags |= FS_IMMUTABLE_FL;
> +	return flags;
> +}
> +
> +static int
> +efivarfs_ioc_getxflags(struct file *file, void __user *arg)
> +{
> +	struct inode *inode = file->f_mapping->host;
> +	unsigned int flags = efivarfs_getflags(inode);
>  
>  	if (copy_to_user(arg, &flags, sizeof(flags)))
>  		return -EFAULT;
> @@ -132,6 +138,7 @@ efivarfs_ioc_setxflags(struct file *file, void __user *arg)
>  	struct inode *inode = file->f_mapping->host;
>  	unsigned int flags;
>  	unsigned int i_flags = 0;
> +	unsigned int oldflags = efivarfs_getflags(inode);
>  	int error;
>  
>  	if (!inode_owner_or_capable(inode))
> @@ -143,8 +150,9 @@ efivarfs_ioc_setxflags(struct file *file, void __user *arg)
>  	if (flags & ~FS_IMMUTABLE_FL)
>  		return -EOPNOTSUPP;
>  
> -	if (!capable(CAP_LINUX_IMMUTABLE))
> -		return -EPERM;
> +	error = vfs_ioc_setflags_check(inode, oldflags, flags);
> +	if (error)
> +		return error;
>  
>  	if (flags & FS_IMMUTABLE_FL)
>  		i_flags |= S_IMMUTABLE;
> diff --git a/fs/ext2/ioctl.c b/fs/ext2/ioctl.c
> index 0367c0039e68..88b3b9720023 100644
> --- a/fs/ext2/ioctl.c
> +++ b/fs/ext2/ioctl.c
> @@ -60,18 +60,10 @@ long ext2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
>  		}
>  		oldflags = ei->i_flags;
>  
> -		/*
> -		 * The IMMUTABLE and APPEND_ONLY flags can only be changed by
> -		 * the relevant capability.
> -		 *
> -		 * This test looks nicer. Thanks to Pauline Middelink
> -		 */
> -		if ((flags ^ oldflags) & (EXT2_APPEND_FL | EXT2_IMMUTABLE_FL)) {
> -			if (!capable(CAP_LINUX_IMMUTABLE)) {
> -				inode_unlock(inode);
> -				ret = -EPERM;
> -				goto setflags_out;
> -			}
> +		ret = vfs_ioc_setflags_check(inode, oldflags, flags);
> +		if (ret) {
> +			inode_unlock(inode);
> +			goto setflags_out;
>  		}
>  
>  		flags = flags & EXT2_FL_USER_MODIFIABLE;
> diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
> index e486e49b31ed..5126ee351a84 100644
> --- a/fs/ext4/ioctl.c
> +++ b/fs/ext4/ioctl.c
> @@ -289,16 +289,9 @@ static int ext4_ioctl_setflags(struct inode *inode,
>  	/* The JOURNAL_DATA flag is modifiable only by root */
>  	jflag = flags & EXT4_JOURNAL_DATA_FL;
>  
> -	/*
> -	 * The IMMUTABLE and APPEND_ONLY flags can only be changed by
> -	 * the relevant capability.
> -	 *
> -	 * This test looks nicer. Thanks to Pauline Middelink
> -	 */
> -	if ((flags ^ oldflags) & (EXT4_APPEND_FL | EXT4_IMMUTABLE_FL)) {
> -		if (!capable(CAP_LINUX_IMMUTABLE))
> -			goto flags_out;
> -	}
> +	err = vfs_ioc_setflags_check(inode, oldflags, flags);
> +	if (err)
> +		goto flags_out;
>  
>  	/*
>  	 * The JOURNAL_DATA flag can only be changed by
> diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
> index 45b45f37d347..a969d5497e03 100644
> --- a/fs/f2fs/file.c
> +++ b/fs/f2fs/file.c
> @@ -1670,6 +1670,7 @@ static int __f2fs_ioc_setflags(struct inode *inode, unsigned int flags)
>  {
>  	struct f2fs_inode_info *fi = F2FS_I(inode);
>  	unsigned int oldflags;
> +	int err;
>  
>  	/* Is it quota file? Do not allow user to mess with it */
>  	if (IS_NOQUOTA(inode))
> @@ -1679,9 +1680,9 @@ static int __f2fs_ioc_setflags(struct inode *inode, unsigned int flags)
>  
>  	oldflags = fi->i_flags;
>  
> -	if ((flags ^ oldflags) & (F2FS_APPEND_FL | F2FS_IMMUTABLE_FL))
> -		if (!capable(CAP_LINUX_IMMUTABLE))
> -			return -EPERM;
> +	err = vfs_ioc_setflags_check(inode, oldflags, flags);
> +	if (err)
> +		return err;
>  
>  	flags = flags & F2FS_FL_USER_MODIFIABLE;
>  	flags |= oldflags & ~F2FS_FL_USER_MODIFIABLE;
> diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c
> index d174b1f8fd08..99f53cf699c6 100644
> --- a/fs/gfs2/file.c
> +++ b/fs/gfs2/file.c
> @@ -136,27 +136,36 @@ static struct {
>  	{FS_JOURNAL_DATA_FL, GFS2_DIF_JDATA | GFS2_DIF_INHERIT_JDATA},
>  };
>  
> +static inline u32 gfs2_gfsflags_to_fsflags(struct inode *inode, u32 gfsflags)
> +{
> +	int i;
> +	u32 fsflags = 0;
> +
> +	if (S_ISDIR(inode->i_mode))
> +		gfsflags &= ~GFS2_DIF_JDATA;
> +	else
> +		gfsflags &= ~GFS2_DIF_INHERIT_JDATA;
> +
> +	for (i = 0; i < ARRAY_SIZE(fsflag_gfs2flag); i++)
> +		if (gfsflags & fsflag_gfs2flag[i].gfsflag)
> +			fsflags |= fsflag_gfs2flag[i].fsflag;
> +	return fsflags;
> +}
> +
>  static int gfs2_get_flags(struct file *filp, u32 __user *ptr)
>  {
>  	struct inode *inode = file_inode(filp);
>  	struct gfs2_inode *ip = GFS2_I(inode);
>  	struct gfs2_holder gh;
> -	int i, error;
> -	u32 gfsflags, fsflags = 0;
> +	int error;
> +	u32 fsflags;
>  
>  	gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &gh);
>  	error = gfs2_glock_nq(&gh);
>  	if (error)
>  		goto out_uninit;
>  
> -	gfsflags = ip->i_diskflags;
> -	if (S_ISDIR(inode->i_mode))
> -		gfsflags &= ~GFS2_DIF_JDATA;
> -	else
> -		gfsflags &= ~GFS2_DIF_INHERIT_JDATA;
> -	for (i = 0; i < ARRAY_SIZE(fsflag_gfs2flag); i++)
> -		if (gfsflags & fsflag_gfs2flag[i].gfsflag)
> -			fsflags |= fsflag_gfs2flag[i].fsflag;
> +	fsflags = gfs2_gfsflags_to_fsflags(inode, ip->i_diskflags);
>  
>  	if (put_user(fsflags, ptr))
>  		error = -EFAULT;
> @@ -200,9 +209,11 @@ void gfs2_set_inode_flags(struct inode *inode)
>   * @filp: file pointer
>   * @reqflags: The flags to set
>   * @mask: Indicates which flags are valid
> + * @fsflags: The FS_* inode flags passed in
>   *
>   */
> -static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask)
> +static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask,
> +			     const u32 fsflags)
>  {
>  	struct inode *inode = file_inode(filp);
>  	struct gfs2_inode *ip = GFS2_I(inode);
> @@ -210,7 +221,7 @@ static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask)
>  	struct buffer_head *bh;
>  	struct gfs2_holder gh;
>  	int error;
> -	u32 new_flags, flags;
> +	u32 new_flags, flags, oldflags;
>  
>  	error = mnt_want_write_file(filp);
>  	if (error)
> @@ -220,6 +231,11 @@ static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask)
>  	if (error)
>  		goto out_drop_write;
>  
> +	oldflags = gfs2_gfsflags_to_fsflags(inode, ip->i_diskflags);
> +	error = vfs_ioc_setflags_check(inode, oldflags, fsflags);
> +	if (error)
> +		goto out;
> +
>  	error = -EACCES;
>  	if (!inode_owner_or_capable(inode))
>  		goto out;
> @@ -308,7 +324,7 @@ static int gfs2_set_flags(struct file *filp, u32 __user *ptr)
>  		mask &= ~(GFS2_DIF_TOPDIR | GFS2_DIF_INHERIT_JDATA);
>  	}
>  
> -	return do_gfs2_set_flags(filp, gfsflags, mask);
> +	return do_gfs2_set_flags(filp, gfsflags, mask, fsflags);
>  }
>  
>  static int gfs2_getlabel(struct file *filp, char __user *label)
> diff --git a/fs/hfsplus/ioctl.c b/fs/hfsplus/ioctl.c
> index 5e6502ef7415..862a3c9481d7 100644
> --- a/fs/hfsplus/ioctl.c
> +++ b/fs/hfsplus/ioctl.c
> @@ -57,9 +57,8 @@ static int hfsplus_ioctl_bless(struct file *file, int __user *user_flags)
>  	return 0;
>  }
>  
> -static int hfsplus_ioctl_getflags(struct file *file, int __user *user_flags)
> +static inline unsigned int hfsplus_getflags(struct inode *inode)
>  {
> -	struct inode *inode = file_inode(file);
>  	struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
>  	unsigned int flags = 0;
>  
> @@ -69,6 +68,13 @@ static int hfsplus_ioctl_getflags(struct file *file, int __user *user_flags)
>  		flags |= FS_APPEND_FL;
>  	if (hip->userflags & HFSPLUS_FLG_NODUMP)
>  		flags |= FS_NODUMP_FL;
> +	return flags;
> +}
> +
> +static int hfsplus_ioctl_getflags(struct file *file, int __user *user_flags)
> +{
> +	struct inode *inode = file_inode(file);
> +	unsigned int flags = hfsplus_getflags(inode);
>  
>  	return put_user(flags, user_flags);
>  }
> @@ -78,6 +84,7 @@ static int hfsplus_ioctl_setflags(struct file *file, int __user *user_flags)
>  	struct inode *inode = file_inode(file);
>  	struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
>  	unsigned int flags, new_fl = 0;
> +	unsigned int oldflags = hfsplus_getflags(inode);
>  	int err = 0;
>  
>  	err = mnt_want_write_file(file);
> @@ -96,13 +103,9 @@ static int hfsplus_ioctl_setflags(struct file *file, int __user *user_flags)
>  
>  	inode_lock(inode);
>  
> -	if ((flags & (FS_IMMUTABLE_FL|FS_APPEND_FL)) ||
> -	    inode->i_flags & (S_IMMUTABLE|S_APPEND)) {
> -		if (!capable(CAP_LINUX_IMMUTABLE)) {
> -			err = -EPERM;
> -			goto out_unlock_inode;
> -		}
> -	}
> +	err = vfs_ioc_setflags_check(inode, oldflags, flags);
> +	if (err)
> +		goto out_unlock_inode;
>  
>  	/* don't silently ignore unsupported ext2 flags */
>  	if (flags & ~(FS_IMMUTABLE_FL|FS_APPEND_FL|FS_NODUMP_FL)) {
> diff --git a/fs/inode.c b/fs/inode.c
> index df6542ec3b88..0ce60b720608 100644
> --- a/fs/inode.c
> +++ b/fs/inode.c
> @@ -2170,3 +2170,20 @@ struct timespec64 current_time(struct inode *inode)
>  	return timespec64_trunc(now, inode->i_sb->s_time_gran);
>  }
>  EXPORT_SYMBOL(current_time);
> +
> +/* Generic function to check FS_IOC_SETFLAGS values. */
> +int vfs_ioc_setflags_check(struct inode *inode, int oldflags, int flags)
> +{
> +	/*
> +	 * The IMMUTABLE and APPEND_ONLY flags can only be changed by
> +	 * the relevant capability.
> +	 *
> +	 * This test looks nicer. Thanks to Pauline Middelink
> +	 */
> +	if ((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL) &&
> +	    !capable(CAP_LINUX_IMMUTABLE))
> +		return -EPERM;
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(vfs_ioc_setflags_check);
> diff --git a/fs/jfs/ioctl.c b/fs/jfs/ioctl.c
> index ba34dae8bd9f..b485c2d7620f 100644
> --- a/fs/jfs/ioctl.c
> +++ b/fs/jfs/ioctl.c
> @@ -98,24 +98,16 @@ long jfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
>  		/* Lock against other parallel changes of flags */
>  		inode_lock(inode);
>  
> -		oldflags = jfs_inode->mode2;
> -
> -		/*
> -		 * The IMMUTABLE and APPEND_ONLY flags can only be changed by
> -		 * the relevant capability.
> -		 */
> -		if ((oldflags & JFS_IMMUTABLE_FL) ||
> -			((flags ^ oldflags) &
> -			(JFS_APPEND_FL | JFS_IMMUTABLE_FL))) {
> -			if (!capable(CAP_LINUX_IMMUTABLE)) {
> -				inode_unlock(inode);
> -				err = -EPERM;
> -				goto setflags_out;
> -			}
> +		oldflags = jfs_map_ext2(jfs_inode->mode2 & JFS_FL_USER_VISIBLE,
> +					0);
> +		err = vfs_ioc_setflags_check(inode, oldflags, flags);
> +		if (err) {
> +			inode_unlock(inode);
> +			goto setflags_out;
>  		}
>  
>  		flags = flags & JFS_FL_USER_MODIFIABLE;
> -		flags |= oldflags & ~JFS_FL_USER_MODIFIABLE;
> +		flags |= jfs_inode->mode2 & ~JFS_FL_USER_MODIFIABLE;
>  		jfs_inode->mode2 = flags;
>  
>  		jfs_set_inode_flags(inode);
> diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c
> index 9b96d79eea6c..0632336d2515 100644
> --- a/fs/nilfs2/ioctl.c
> +++ b/fs/nilfs2/ioctl.c
> @@ -148,13 +148,8 @@ static int nilfs_ioctl_setflags(struct inode *inode, struct file *filp,
>  
>  	oldflags = NILFS_I(inode)->i_flags;
>  
> -	/*
> -	 * The IMMUTABLE and APPEND_ONLY flags can only be changed by the
> -	 * relevant capability.
> -	 */
> -	ret = -EPERM;
> -	if (((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL)) &&
> -	    !capable(CAP_LINUX_IMMUTABLE))
> +	ret = vfs_ioc_setflags_check(inode, oldflags, flags);
> +	if (ret)
>  		goto out;
>  
>  	ret = nilfs_transaction_begin(inode->i_sb, &ti, 0);
> diff --git a/fs/ocfs2/ioctl.c b/fs/ocfs2/ioctl.c
> index 994726ada857..467a2faf0305 100644
> --- a/fs/ocfs2/ioctl.c
> +++ b/fs/ocfs2/ioctl.c
> @@ -106,16 +106,9 @@ static int ocfs2_set_inode_attr(struct inode *inode, unsigned flags,
>  	flags = flags & mask;
>  	flags |= oldflags & ~mask;
>  
> -	/*
> -	 * The IMMUTABLE and APPEND_ONLY flags can only be changed by
> -	 * the relevant capability.
> -	 */
> -	status = -EPERM;
> -	if ((oldflags & OCFS2_IMMUTABLE_FL) || ((flags ^ oldflags) &
> -		(OCFS2_APPEND_FL | OCFS2_IMMUTABLE_FL))) {
> -		if (!capable(CAP_LINUX_IMMUTABLE))
> -			goto bail_unlock;
> -	}
> +	status = vfs_ioc_setflags_check(inode, oldflags, flags);
> +	if (status)
> +		goto bail_unlock;
>  
>  	handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);
>  	if (IS_ERR(handle)) {
> diff --git a/fs/reiserfs/ioctl.c b/fs/reiserfs/ioctl.c
> index acbbaf7a0bb2..92bcb1ecd994 100644
> --- a/fs/reiserfs/ioctl.c
> +++ b/fs/reiserfs/ioctl.c
> @@ -74,13 +74,11 @@ long reiserfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
>  				err = -EPERM;
>  				goto setflags_out;
>  			}
> -			if (((flags ^ REISERFS_I(inode)->
> -			      i_attrs) & (REISERFS_IMMUTABLE_FL |
> -					  REISERFS_APPEND_FL))
> -			    && !capable(CAP_LINUX_IMMUTABLE)) {
> -				err = -EPERM;
> +			err = vfs_ioc_setflags_check(inode,
> +						     REISERFS_I(inode)->i_attrs,
> +						     flags);
> +			if (err)
>  				goto setflags_out;
> -			}
>  			if ((flags & REISERFS_NOTAIL_FL) &&
>  			    S_ISREG(inode->i_mode)) {
>  				int result;
> diff --git a/fs/ubifs/ioctl.c b/fs/ubifs/ioctl.c
> index 4f1a397fda69..bdea836fc38b 100644
> --- a/fs/ubifs/ioctl.c
> +++ b/fs/ubifs/ioctl.c
> @@ -107,18 +107,11 @@ static int setflags(struct inode *inode, int flags)
>  	if (err)
>  		return err;
>  
> -	/*
> -	 * The IMMUTABLE and APPEND_ONLY flags can only be changed by
> -	 * the relevant capability.
> -	 */
>  	mutex_lock(&ui->ui_mutex);
>  	oldflags = ubifs2ioctl(ui->flags);
> -	if ((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL)) {
> -		if (!capable(CAP_LINUX_IMMUTABLE)) {
> -			err = -EPERM;
> -			goto out_unlock;
> -		}
> -	}
> +	err = vfs_ioc_setflags_check(inode, oldflags, flags);
> +	if (err)
> +		goto out_unlock;
>  
>  	ui->flags = ioctl2ubifs(flags);
>  	ubifs_set_inode_flags(inode);
> diff --git a/include/linux/fs.h b/include/linux/fs.h
> index f7fdfe93e25d..1825d055808c 100644
> --- a/include/linux/fs.h
> +++ b/include/linux/fs.h
> @@ -3546,4 +3546,6 @@ static inline struct sock *io_uring_get_socket(struct file *file)
>  }
>  #endif
>  
> +int vfs_ioc_setflags_check(struct inode *inode, int oldflags, int flags);
> +
>  #endif /* _LINUX_FS_H */
> 
-- 
Jan Kara <jack@suse.com>
SUSE Labs, CR


_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

^ permalink raw reply

* Re: [PATCH v2 1/4] vfs: create a generic checking function for FS_IOC_SETFLAGS
From: Jan Kara @ 2019-06-20 13:34 UTC (permalink / raw)
  To: Darrick J. Wong
  Cc: matthew.garrett, yuchao0, tytso, shaggy, ard.biesheuvel, josef,
	clm, adilger.kernel, jk, jack, dsterba, jaegeuk, viro,
	cluster-devel, jfs-discussion, linux-efi, reiserfs-devel,
	linux-kernel, linux-f2fs-devel, linux-xfs, linux-nilfs, linux-mtd,
	ocfs2-devel, linux-fsdevel, linux-ext4, linux-btrfs
In-Reply-To: <20190612004258.GX1871505@magnolia>

On Tue 11-06-19 17:42:58, Darrick J. Wong wrote:
> From: Darrick J. Wong <darrick.wong@oracle.com>
> 
> Create a generic checking function for the incoming FS_IOC_SETFLAGS flag
> values so that we can standardize the implementations that follow ext4's
> flag values.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>

The patch looks good to me. You can add:

Reviewed-by: Jan Kara <jack@suse.cz>

								Honza

> ---
> v2: fix jfs locking and remove its opencoded flags check
> ---
>  fs/btrfs/ioctl.c    |   13 +++++--------
>  fs/efivarfs/file.c  |   18 +++++++++++++-----
>  fs/ext2/ioctl.c     |   16 ++++------------
>  fs/ext4/ioctl.c     |   13 +++----------
>  fs/f2fs/file.c      |    7 ++++---
>  fs/gfs2/file.c      |   42 +++++++++++++++++++++++++++++-------------
>  fs/hfsplus/ioctl.c  |   21 ++++++++++++---------
>  fs/inode.c          |   17 +++++++++++++++++
>  fs/jfs/ioctl.c      |   22 +++++++---------------
>  fs/nilfs2/ioctl.c   |    9 ++-------
>  fs/ocfs2/ioctl.c    |   13 +++----------
>  fs/reiserfs/ioctl.c |   10 ++++------
>  fs/ubifs/ioctl.c    |   13 +++----------
>  include/linux/fs.h  |    2 ++
>  14 files changed, 108 insertions(+), 108 deletions(-)
> 
> diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
> index 6dafa857bbb9..f408aa93b0cf 100644
> --- a/fs/btrfs/ioctl.c
> +++ b/fs/btrfs/ioctl.c
> @@ -187,7 +187,7 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
>  	struct btrfs_inode *binode = BTRFS_I(inode);
>  	struct btrfs_root *root = binode->root;
>  	struct btrfs_trans_handle *trans;
> -	unsigned int fsflags;
> +	unsigned int fsflags, old_fsflags;
>  	int ret;
>  	const char *comp = NULL;
>  	u32 binode_flags = binode->flags;
> @@ -212,13 +212,10 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
>  	inode_lock(inode);
>  
>  	fsflags = btrfs_mask_fsflags_for_type(inode, fsflags);
> -	if ((fsflags ^ btrfs_inode_flags_to_fsflags(binode->flags)) &
> -	    (FS_APPEND_FL | FS_IMMUTABLE_FL)) {
> -		if (!capable(CAP_LINUX_IMMUTABLE)) {
> -			ret = -EPERM;
> -			goto out_unlock;
> -		}
> -	}
> +	old_fsflags = btrfs_inode_flags_to_fsflags(binode->flags);
> +	ret = vfs_ioc_setflags_check(inode, old_fsflags, fsflags);
> +	if (ret)
> +		goto out_unlock;
>  
>  	if (fsflags & FS_SYNC_FL)
>  		binode_flags |= BTRFS_INODE_SYNC;
> diff --git a/fs/efivarfs/file.c b/fs/efivarfs/file.c
> index 8e568428c88b..f4f6c1bec132 100644
> --- a/fs/efivarfs/file.c
> +++ b/fs/efivarfs/file.c
> @@ -110,16 +110,22 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf,
>  	return size;
>  }
>  
> -static int
> -efivarfs_ioc_getxflags(struct file *file, void __user *arg)
> +static inline unsigned int efivarfs_getflags(struct inode *inode)
>  {
> -	struct inode *inode = file->f_mapping->host;
>  	unsigned int i_flags;
>  	unsigned int flags = 0;
>  
>  	i_flags = inode->i_flags;
>  	if (i_flags & S_IMMUTABLE)
>  		flags |= FS_IMMUTABLE_FL;
> +	return flags;
> +}
> +
> +static int
> +efivarfs_ioc_getxflags(struct file *file, void __user *arg)
> +{
> +	struct inode *inode = file->f_mapping->host;
> +	unsigned int flags = efivarfs_getflags(inode);
>  
>  	if (copy_to_user(arg, &flags, sizeof(flags)))
>  		return -EFAULT;
> @@ -132,6 +138,7 @@ efivarfs_ioc_setxflags(struct file *file, void __user *arg)
>  	struct inode *inode = file->f_mapping->host;
>  	unsigned int flags;
>  	unsigned int i_flags = 0;
> +	unsigned int oldflags = efivarfs_getflags(inode);
>  	int error;
>  
>  	if (!inode_owner_or_capable(inode))
> @@ -143,8 +150,9 @@ efivarfs_ioc_setxflags(struct file *file, void __user *arg)
>  	if (flags & ~FS_IMMUTABLE_FL)
>  		return -EOPNOTSUPP;
>  
> -	if (!capable(CAP_LINUX_IMMUTABLE))
> -		return -EPERM;
> +	error = vfs_ioc_setflags_check(inode, oldflags, flags);
> +	if (error)
> +		return error;
>  
>  	if (flags & FS_IMMUTABLE_FL)
>  		i_flags |= S_IMMUTABLE;
> diff --git a/fs/ext2/ioctl.c b/fs/ext2/ioctl.c
> index 0367c0039e68..88b3b9720023 100644
> --- a/fs/ext2/ioctl.c
> +++ b/fs/ext2/ioctl.c
> @@ -60,18 +60,10 @@ long ext2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
>  		}
>  		oldflags = ei->i_flags;
>  
> -		/*
> -		 * The IMMUTABLE and APPEND_ONLY flags can only be changed by
> -		 * the relevant capability.
> -		 *
> -		 * This test looks nicer. Thanks to Pauline Middelink
> -		 */
> -		if ((flags ^ oldflags) & (EXT2_APPEND_FL | EXT2_IMMUTABLE_FL)) {
> -			if (!capable(CAP_LINUX_IMMUTABLE)) {
> -				inode_unlock(inode);
> -				ret = -EPERM;
> -				goto setflags_out;
> -			}
> +		ret = vfs_ioc_setflags_check(inode, oldflags, flags);
> +		if (ret) {
> +			inode_unlock(inode);
> +			goto setflags_out;
>  		}
>  
>  		flags = flags & EXT2_FL_USER_MODIFIABLE;
> diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
> index e486e49b31ed..5126ee351a84 100644
> --- a/fs/ext4/ioctl.c
> +++ b/fs/ext4/ioctl.c
> @@ -289,16 +289,9 @@ static int ext4_ioctl_setflags(struct inode *inode,
>  	/* The JOURNAL_DATA flag is modifiable only by root */
>  	jflag = flags & EXT4_JOURNAL_DATA_FL;
>  
> -	/*
> -	 * The IMMUTABLE and APPEND_ONLY flags can only be changed by
> -	 * the relevant capability.
> -	 *
> -	 * This test looks nicer. Thanks to Pauline Middelink
> -	 */
> -	if ((flags ^ oldflags) & (EXT4_APPEND_FL | EXT4_IMMUTABLE_FL)) {
> -		if (!capable(CAP_LINUX_IMMUTABLE))
> -			goto flags_out;
> -	}
> +	err = vfs_ioc_setflags_check(inode, oldflags, flags);
> +	if (err)
> +		goto flags_out;
>  
>  	/*
>  	 * The JOURNAL_DATA flag can only be changed by
> diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
> index 45b45f37d347..a969d5497e03 100644
> --- a/fs/f2fs/file.c
> +++ b/fs/f2fs/file.c
> @@ -1670,6 +1670,7 @@ static int __f2fs_ioc_setflags(struct inode *inode, unsigned int flags)
>  {
>  	struct f2fs_inode_info *fi = F2FS_I(inode);
>  	unsigned int oldflags;
> +	int err;
>  
>  	/* Is it quota file? Do not allow user to mess with it */
>  	if (IS_NOQUOTA(inode))
> @@ -1679,9 +1680,9 @@ static int __f2fs_ioc_setflags(struct inode *inode, unsigned int flags)
>  
>  	oldflags = fi->i_flags;
>  
> -	if ((flags ^ oldflags) & (F2FS_APPEND_FL | F2FS_IMMUTABLE_FL))
> -		if (!capable(CAP_LINUX_IMMUTABLE))
> -			return -EPERM;
> +	err = vfs_ioc_setflags_check(inode, oldflags, flags);
> +	if (err)
> +		return err;
>  
>  	flags = flags & F2FS_FL_USER_MODIFIABLE;
>  	flags |= oldflags & ~F2FS_FL_USER_MODIFIABLE;
> diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c
> index d174b1f8fd08..99f53cf699c6 100644
> --- a/fs/gfs2/file.c
> +++ b/fs/gfs2/file.c
> @@ -136,27 +136,36 @@ static struct {
>  	{FS_JOURNAL_DATA_FL, GFS2_DIF_JDATA | GFS2_DIF_INHERIT_JDATA},
>  };
>  
> +static inline u32 gfs2_gfsflags_to_fsflags(struct inode *inode, u32 gfsflags)
> +{
> +	int i;
> +	u32 fsflags = 0;
> +
> +	if (S_ISDIR(inode->i_mode))
> +		gfsflags &= ~GFS2_DIF_JDATA;
> +	else
> +		gfsflags &= ~GFS2_DIF_INHERIT_JDATA;
> +
> +	for (i = 0; i < ARRAY_SIZE(fsflag_gfs2flag); i++)
> +		if (gfsflags & fsflag_gfs2flag[i].gfsflag)
> +			fsflags |= fsflag_gfs2flag[i].fsflag;
> +	return fsflags;
> +}
> +
>  static int gfs2_get_flags(struct file *filp, u32 __user *ptr)
>  {
>  	struct inode *inode = file_inode(filp);
>  	struct gfs2_inode *ip = GFS2_I(inode);
>  	struct gfs2_holder gh;
> -	int i, error;
> -	u32 gfsflags, fsflags = 0;
> +	int error;
> +	u32 fsflags;
>  
>  	gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &gh);
>  	error = gfs2_glock_nq(&gh);
>  	if (error)
>  		goto out_uninit;
>  
> -	gfsflags = ip->i_diskflags;
> -	if (S_ISDIR(inode->i_mode))
> -		gfsflags &= ~GFS2_DIF_JDATA;
> -	else
> -		gfsflags &= ~GFS2_DIF_INHERIT_JDATA;
> -	for (i = 0; i < ARRAY_SIZE(fsflag_gfs2flag); i++)
> -		if (gfsflags & fsflag_gfs2flag[i].gfsflag)
> -			fsflags |= fsflag_gfs2flag[i].fsflag;
> +	fsflags = gfs2_gfsflags_to_fsflags(inode, ip->i_diskflags);
>  
>  	if (put_user(fsflags, ptr))
>  		error = -EFAULT;
> @@ -200,9 +209,11 @@ void gfs2_set_inode_flags(struct inode *inode)
>   * @filp: file pointer
>   * @reqflags: The flags to set
>   * @mask: Indicates which flags are valid
> + * @fsflags: The FS_* inode flags passed in
>   *
>   */
> -static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask)
> +static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask,
> +			     const u32 fsflags)
>  {
>  	struct inode *inode = file_inode(filp);
>  	struct gfs2_inode *ip = GFS2_I(inode);
> @@ -210,7 +221,7 @@ static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask)
>  	struct buffer_head *bh;
>  	struct gfs2_holder gh;
>  	int error;
> -	u32 new_flags, flags;
> +	u32 new_flags, flags, oldflags;
>  
>  	error = mnt_want_write_file(filp);
>  	if (error)
> @@ -220,6 +231,11 @@ static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask)
>  	if (error)
>  		goto out_drop_write;
>  
> +	oldflags = gfs2_gfsflags_to_fsflags(inode, ip->i_diskflags);
> +	error = vfs_ioc_setflags_check(inode, oldflags, fsflags);
> +	if (error)
> +		goto out;
> +
>  	error = -EACCES;
>  	if (!inode_owner_or_capable(inode))
>  		goto out;
> @@ -308,7 +324,7 @@ static int gfs2_set_flags(struct file *filp, u32 __user *ptr)
>  		mask &= ~(GFS2_DIF_TOPDIR | GFS2_DIF_INHERIT_JDATA);
>  	}
>  
> -	return do_gfs2_set_flags(filp, gfsflags, mask);
> +	return do_gfs2_set_flags(filp, gfsflags, mask, fsflags);
>  }
>  
>  static int gfs2_getlabel(struct file *filp, char __user *label)
> diff --git a/fs/hfsplus/ioctl.c b/fs/hfsplus/ioctl.c
> index 5e6502ef7415..862a3c9481d7 100644
> --- a/fs/hfsplus/ioctl.c
> +++ b/fs/hfsplus/ioctl.c
> @@ -57,9 +57,8 @@ static int hfsplus_ioctl_bless(struct file *file, int __user *user_flags)
>  	return 0;
>  }
>  
> -static int hfsplus_ioctl_getflags(struct file *file, int __user *user_flags)
> +static inline unsigned int hfsplus_getflags(struct inode *inode)
>  {
> -	struct inode *inode = file_inode(file);
>  	struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
>  	unsigned int flags = 0;
>  
> @@ -69,6 +68,13 @@ static int hfsplus_ioctl_getflags(struct file *file, int __user *user_flags)
>  		flags |= FS_APPEND_FL;
>  	if (hip->userflags & HFSPLUS_FLG_NODUMP)
>  		flags |= FS_NODUMP_FL;
> +	return flags;
> +}
> +
> +static int hfsplus_ioctl_getflags(struct file *file, int __user *user_flags)
> +{
> +	struct inode *inode = file_inode(file);
> +	unsigned int flags = hfsplus_getflags(inode);
>  
>  	return put_user(flags, user_flags);
>  }
> @@ -78,6 +84,7 @@ static int hfsplus_ioctl_setflags(struct file *file, int __user *user_flags)
>  	struct inode *inode = file_inode(file);
>  	struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
>  	unsigned int flags, new_fl = 0;
> +	unsigned int oldflags = hfsplus_getflags(inode);
>  	int err = 0;
>  
>  	err = mnt_want_write_file(file);
> @@ -96,13 +103,9 @@ static int hfsplus_ioctl_setflags(struct file *file, int __user *user_flags)
>  
>  	inode_lock(inode);
>  
> -	if ((flags & (FS_IMMUTABLE_FL|FS_APPEND_FL)) ||
> -	    inode->i_flags & (S_IMMUTABLE|S_APPEND)) {
> -		if (!capable(CAP_LINUX_IMMUTABLE)) {
> -			err = -EPERM;
> -			goto out_unlock_inode;
> -		}
> -	}
> +	err = vfs_ioc_setflags_check(inode, oldflags, flags);
> +	if (err)
> +		goto out_unlock_inode;
>  
>  	/* don't silently ignore unsupported ext2 flags */
>  	if (flags & ~(FS_IMMUTABLE_FL|FS_APPEND_FL|FS_NODUMP_FL)) {
> diff --git a/fs/inode.c b/fs/inode.c
> index df6542ec3b88..0ce60b720608 100644
> --- a/fs/inode.c
> +++ b/fs/inode.c
> @@ -2170,3 +2170,20 @@ struct timespec64 current_time(struct inode *inode)
>  	return timespec64_trunc(now, inode->i_sb->s_time_gran);
>  }
>  EXPORT_SYMBOL(current_time);
> +
> +/* Generic function to check FS_IOC_SETFLAGS values. */
> +int vfs_ioc_setflags_check(struct inode *inode, int oldflags, int flags)
> +{
> +	/*
> +	 * The IMMUTABLE and APPEND_ONLY flags can only be changed by
> +	 * the relevant capability.
> +	 *
> +	 * This test looks nicer. Thanks to Pauline Middelink
> +	 */
> +	if ((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL) &&
> +	    !capable(CAP_LINUX_IMMUTABLE))
> +		return -EPERM;
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(vfs_ioc_setflags_check);
> diff --git a/fs/jfs/ioctl.c b/fs/jfs/ioctl.c
> index ba34dae8bd9f..b485c2d7620f 100644
> --- a/fs/jfs/ioctl.c
> +++ b/fs/jfs/ioctl.c
> @@ -98,24 +98,16 @@ long jfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
>  		/* Lock against other parallel changes of flags */
>  		inode_lock(inode);
>  
> -		oldflags = jfs_inode->mode2;
> -
> -		/*
> -		 * The IMMUTABLE and APPEND_ONLY flags can only be changed by
> -		 * the relevant capability.
> -		 */
> -		if ((oldflags & JFS_IMMUTABLE_FL) ||
> -			((flags ^ oldflags) &
> -			(JFS_APPEND_FL | JFS_IMMUTABLE_FL))) {
> -			if (!capable(CAP_LINUX_IMMUTABLE)) {
> -				inode_unlock(inode);
> -				err = -EPERM;
> -				goto setflags_out;
> -			}
> +		oldflags = jfs_map_ext2(jfs_inode->mode2 & JFS_FL_USER_VISIBLE,
> +					0);
> +		err = vfs_ioc_setflags_check(inode, oldflags, flags);
> +		if (err) {
> +			inode_unlock(inode);
> +			goto setflags_out;
>  		}
>  
>  		flags = flags & JFS_FL_USER_MODIFIABLE;
> -		flags |= oldflags & ~JFS_FL_USER_MODIFIABLE;
> +		flags |= jfs_inode->mode2 & ~JFS_FL_USER_MODIFIABLE;
>  		jfs_inode->mode2 = flags;
>  
>  		jfs_set_inode_flags(inode);
> diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c
> index 9b96d79eea6c..0632336d2515 100644
> --- a/fs/nilfs2/ioctl.c
> +++ b/fs/nilfs2/ioctl.c
> @@ -148,13 +148,8 @@ static int nilfs_ioctl_setflags(struct inode *inode, struct file *filp,
>  
>  	oldflags = NILFS_I(inode)->i_flags;
>  
> -	/*
> -	 * The IMMUTABLE and APPEND_ONLY flags can only be changed by the
> -	 * relevant capability.
> -	 */
> -	ret = -EPERM;
> -	if (((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL)) &&
> -	    !capable(CAP_LINUX_IMMUTABLE))
> +	ret = vfs_ioc_setflags_check(inode, oldflags, flags);
> +	if (ret)
>  		goto out;
>  
>  	ret = nilfs_transaction_begin(inode->i_sb, &ti, 0);
> diff --git a/fs/ocfs2/ioctl.c b/fs/ocfs2/ioctl.c
> index 994726ada857..467a2faf0305 100644
> --- a/fs/ocfs2/ioctl.c
> +++ b/fs/ocfs2/ioctl.c
> @@ -106,16 +106,9 @@ static int ocfs2_set_inode_attr(struct inode *inode, unsigned flags,
>  	flags = flags & mask;
>  	flags |= oldflags & ~mask;
>  
> -	/*
> -	 * The IMMUTABLE and APPEND_ONLY flags can only be changed by
> -	 * the relevant capability.
> -	 */
> -	status = -EPERM;
> -	if ((oldflags & OCFS2_IMMUTABLE_FL) || ((flags ^ oldflags) &
> -		(OCFS2_APPEND_FL | OCFS2_IMMUTABLE_FL))) {
> -		if (!capable(CAP_LINUX_IMMUTABLE))
> -			goto bail_unlock;
> -	}
> +	status = vfs_ioc_setflags_check(inode, oldflags, flags);
> +	if (status)
> +		goto bail_unlock;
>  
>  	handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);
>  	if (IS_ERR(handle)) {
> diff --git a/fs/reiserfs/ioctl.c b/fs/reiserfs/ioctl.c
> index acbbaf7a0bb2..92bcb1ecd994 100644
> --- a/fs/reiserfs/ioctl.c
> +++ b/fs/reiserfs/ioctl.c
> @@ -74,13 +74,11 @@ long reiserfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
>  				err = -EPERM;
>  				goto setflags_out;
>  			}
> -			if (((flags ^ REISERFS_I(inode)->
> -			      i_attrs) & (REISERFS_IMMUTABLE_FL |
> -					  REISERFS_APPEND_FL))
> -			    && !capable(CAP_LINUX_IMMUTABLE)) {
> -				err = -EPERM;
> +			err = vfs_ioc_setflags_check(inode,
> +						     REISERFS_I(inode)->i_attrs,
> +						     flags);
> +			if (err)
>  				goto setflags_out;
> -			}
>  			if ((flags & REISERFS_NOTAIL_FL) &&
>  			    S_ISREG(inode->i_mode)) {
>  				int result;
> diff --git a/fs/ubifs/ioctl.c b/fs/ubifs/ioctl.c
> index 4f1a397fda69..bdea836fc38b 100644
> --- a/fs/ubifs/ioctl.c
> +++ b/fs/ubifs/ioctl.c
> @@ -107,18 +107,11 @@ static int setflags(struct inode *inode, int flags)
>  	if (err)
>  		return err;
>  
> -	/*
> -	 * The IMMUTABLE and APPEND_ONLY flags can only be changed by
> -	 * the relevant capability.
> -	 */
>  	mutex_lock(&ui->ui_mutex);
>  	oldflags = ubifs2ioctl(ui->flags);
> -	if ((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL)) {
> -		if (!capable(CAP_LINUX_IMMUTABLE)) {
> -			err = -EPERM;
> -			goto out_unlock;
> -		}
> -	}
> +	err = vfs_ioc_setflags_check(inode, oldflags, flags);
> +	if (err)
> +		goto out_unlock;
>  
>  	ui->flags = ioctl2ubifs(flags);
>  	ubifs_set_inode_flags(inode);
> diff --git a/include/linux/fs.h b/include/linux/fs.h
> index f7fdfe93e25d..1825d055808c 100644
> --- a/include/linux/fs.h
> +++ b/include/linux/fs.h
> @@ -3546,4 +3546,6 @@ static inline struct sock *io_uring_get_socket(struct file *file)
>  }
>  #endif
>  
> +int vfs_ioc_setflags_check(struct inode *inode, int oldflags, int flags);
> +
>  #endif /* _LINUX_FS_H */
> 
-- 
Jan Kara <jack@suse.com>
SUSE Labs, CR

^ permalink raw reply

* Re: [PATCH 3/3] mmc: sdhci-of-arasan: Add support for ZynqMP Platform Tap Delays Setup
From: Ulf Hansson @ 2019-06-20 13:33 UTC (permalink / raw)
  To: Manish Narani
  Cc: Mark Rutland, DTML, Nava kishore Manne, linux-mmc@vger.kernel.org,
	Adrian Hunter, Linux Kernel Mailing List, Jolly Shah, Rajan Vaja,
	Rob Herring, Michal Simek, Olof Johansson, Linux ARM
In-Reply-To: <MN2PR02MB602935234A2A779B5A05CD63C1E40@MN2PR02MB6029.namprd02.prod.outlook.com>

On Thu, 20 Jun 2019 at 10:14, Manish Narani <MNARANI@xilinx.com> wrote:
>
> Hi Uffe,
>
>
> > -----Original Message-----
> > From: Ulf Hansson <ulf.hansson@linaro.org>
> > Sent: Wednesday, June 19, 2019 7:09 PM
> > To: Manish Narani <MNARANI@xilinx.com>
> > Cc: Michal Simek <michals@xilinx.com>; Rob Herring <robh+dt@kernel.org>;
> > Mark Rutland <mark.rutland@arm.com>; Adrian Hunter
> > <adrian.hunter@intel.com>; Rajan Vaja <RAJANV@xilinx.com>; Jolly Shah
> > <JOLLYS@xilinx.com>; Nava kishore Manne <navam@xilinx.com>; Olof
> > Johansson <olof@lixom.net>; linux-mmc@vger.kernel.org; DTML
> > <devicetree@vger.kernel.org>; Linux Kernel Mailing List <linux-
> > kernel@vger.kernel.org>; Linux ARM <linux-arm-kernel@lists.infradead.org>
> > Subject: Re: [PATCH 3/3] mmc: sdhci-of-arasan: Add support for ZynqMP
> > Platform Tap Delays Setup
> >
> > On Wed, 19 Jun 2019 at 10:40, Manish Narani <MNARANI@xilinx.com> wrote:
> > >
> > > Hi Uffe,
> > >
> > >
> > > > -----Original Message-----
> > > > From: Ulf Hansson <ulf.hansson@linaro.org>
> > > > Sent: Monday, June 17, 2019 5:51 PM
> > > [...]
> > > >
> > > > The "const struct zynqmp_eemi_ops *eemi_ops; should then be moved into
> > > > a clock provider specific struct, which is assigned when calling
> > > > sdhci_arasan_register_sdclk. I understand that all the clock data is
> > > > folded into struct sdhci_arasan_data today, but I think that should be
> > > > moved into a "sub-struct" for the clock specifics.
> > > >
> > > > Moreover, when registering the clock, we should convert from using
> > > > devm_clk_register() into devm_clk_hw_register() as the first one is
> > > > now deprecated.
> > >
> > > Just a query here:
> > > When we switch to using devm_clk_hw_register() here, it will register the
> > clk_hw and return int.
> > > Is there a way we can get the clk (related to the clk_hw registered) from the
> > > clock framework?
> > > I am asking this because we will need that clk pointer while calling
> > clk_set_phase() function.
> >
> > I assume devm_clk_get() should work fine?
>
> This clock does not come through ZynqMP Clock framework. We are initializing it in this 'sdhci-of-arasan' driver and getting only the clock name from "clock_output_names" property. So I think devm_clk_get() will not work here for our case.

Well, I guess you need to register an OF clock provider to allow the
clock lookup to work. Apologize, but I don't have the time, currently
to point you in the exact direction.

However, in principle, my point is, there should be no difference
whether the clock is registered via the "ZynqMP Clock framework" or
via the mmc driver. The *clk_get() thing need to work, otherwise I
consider the clock registration in the mmc driver to be a hack. If you
see what I mean.

> I have gone through the clock framework and I found one function which may be used to create clock from clock hw, that is ' clk_hw_create_clk()' which can be used from our driver, however this needs change in the clock framework as below :
>
> ---
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index aa51756..4dc69ff 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -3420,6 +3420,7 @@ struct clk *clk_hw_create_clk(struct device *dev, struct clk_hw *hw,
>
>         return clk;
>  }
> +EXPORT_SYMBOL_GPL(clk_hw_create_clk);
>
>  static int clk_cpy_name(const char **dst_p, const char *src, bool must_exist)
>  {
> diff --git a/drivers/clk/clk.h b/drivers/clk/clk.h
> index d8400d6..2319899 100644
> --- a/drivers/clk/clk.h
> +++ b/drivers/clk/clk.h
> @@ -22,17 +22,9 @@ static inline struct clk_hw *of_clk_get_hw(struct device_node *np,
>  struct clk_hw *clk_find_hw(const char *dev_id, const char *con_id);
>
>  #ifdef CONFIG_COMMON_CLK
> -struct clk *clk_hw_create_clk(struct device *dev, struct clk_hw *hw,
> -                             const char *dev_id, const char *con_id);
>  void __clk_put(struct clk *clk);
>  #else
>  /* All these casts to avoid ifdefs in clkdev... */
> -static inline struct clk *
> -clk_hw_create_clk(struct device *dev, struct clk_hw *hw, const char *dev_id,
> -                 const char *con_id)
> -{
> -       return (struct clk *)hw;
> -}
>  static struct clk_hw *__clk_get_hw(struct clk *clk)
>  {
>         return (struct clk_hw *)clk;
> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index f689fc5..d3f60fe 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -18,6 +18,7 @@
>
>  struct device;
>  struct clk;
> +struct clk_hw;
>  struct device_node;
>  struct of_phandle_args;
>
> @@ -934,4 +935,15 @@ static inline struct clk *of_clk_get_from_provider(struct of_phandle_args *clksp
>  }
>  #endif
>
> +#ifdef CONFIG_COMMON_CLK
> +struct clk *clk_hw_create_clk(struct device *dev, struct clk_hw *hw,
> +                             const char *dev_id, const char *con_id);
> +#else
> +static inline struct clk *
> +clk_hw_create_clk(struct device *dev, struct clk_hw *hw, const char *dev_id,
> +                 const char *con_id)
> +{
> +       return (struct clk *)hw;
> +}
> +#endif
>  #endif
> ---
>
> This change should help other drivers (outside 'drivers/clk/') as well for getting the clock created from clk_hw.
> Is this fine to do?

I think this is the wrong approach, see why further above.

Kind regards
Uffe

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* [Ocfs2-devel] [PATCH v2 1/4] vfs: create a generic checking function for FS_IOC_SETFLAGS
From: Jan Kara @ 2019-06-20 13:34 UTC (permalink / raw)
  To: Darrick J. Wong
  Cc: matthew.garrett, yuchao0, tytso, shaggy, ard.biesheuvel, josef,
	clm, adilger.kernel, jk, jack, dsterba, jaegeuk, viro,
	cluster-devel, jfs-discussion, linux-efi, reiserfs-devel,
	linux-kernel, linux-f2fs-devel, linux-xfs, linux-nilfs, linux-mtd,
	ocfs2-devel, linux-fsdevel, linux-ext4, linux-btrfs
In-Reply-To: <20190612004258.GX1871505@magnolia>

On Tue 11-06-19 17:42:58, Darrick J. Wong wrote:
> From: Darrick J. Wong <darrick.wong@oracle.com>
> 
> Create a generic checking function for the incoming FS_IOC_SETFLAGS flag
> values so that we can standardize the implementations that follow ext4's
> flag values.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>

The patch looks good to me. You can add:

Reviewed-by: Jan Kara <jack@suse.cz>

								Honza

> ---
> v2: fix jfs locking and remove its opencoded flags check
> ---
>  fs/btrfs/ioctl.c    |   13 +++++--------
>  fs/efivarfs/file.c  |   18 +++++++++++++-----
>  fs/ext2/ioctl.c     |   16 ++++------------
>  fs/ext4/ioctl.c     |   13 +++----------
>  fs/f2fs/file.c      |    7 ++++---
>  fs/gfs2/file.c      |   42 +++++++++++++++++++++++++++++-------------
>  fs/hfsplus/ioctl.c  |   21 ++++++++++++---------
>  fs/inode.c          |   17 +++++++++++++++++
>  fs/jfs/ioctl.c      |   22 +++++++---------------
>  fs/nilfs2/ioctl.c   |    9 ++-------
>  fs/ocfs2/ioctl.c    |   13 +++----------
>  fs/reiserfs/ioctl.c |   10 ++++------
>  fs/ubifs/ioctl.c    |   13 +++----------
>  include/linux/fs.h  |    2 ++
>  14 files changed, 108 insertions(+), 108 deletions(-)
> 
> diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
> index 6dafa857bbb9..f408aa93b0cf 100644
> --- a/fs/btrfs/ioctl.c
> +++ b/fs/btrfs/ioctl.c
> @@ -187,7 +187,7 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
>  	struct btrfs_inode *binode = BTRFS_I(inode);
>  	struct btrfs_root *root = binode->root;
>  	struct btrfs_trans_handle *trans;
> -	unsigned int fsflags;
> +	unsigned int fsflags, old_fsflags;
>  	int ret;
>  	const char *comp = NULL;
>  	u32 binode_flags = binode->flags;
> @@ -212,13 +212,10 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
>  	inode_lock(inode);
>  
>  	fsflags = btrfs_mask_fsflags_for_type(inode, fsflags);
> -	if ((fsflags ^ btrfs_inode_flags_to_fsflags(binode->flags)) &
> -	    (FS_APPEND_FL | FS_IMMUTABLE_FL)) {
> -		if (!capable(CAP_LINUX_IMMUTABLE)) {
> -			ret = -EPERM;
> -			goto out_unlock;
> -		}
> -	}
> +	old_fsflags = btrfs_inode_flags_to_fsflags(binode->flags);
> +	ret = vfs_ioc_setflags_check(inode, old_fsflags, fsflags);
> +	if (ret)
> +		goto out_unlock;
>  
>  	if (fsflags & FS_SYNC_FL)
>  		binode_flags |= BTRFS_INODE_SYNC;
> diff --git a/fs/efivarfs/file.c b/fs/efivarfs/file.c
> index 8e568428c88b..f4f6c1bec132 100644
> --- a/fs/efivarfs/file.c
> +++ b/fs/efivarfs/file.c
> @@ -110,16 +110,22 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf,
>  	return size;
>  }
>  
> -static int
> -efivarfs_ioc_getxflags(struct file *file, void __user *arg)
> +static inline unsigned int efivarfs_getflags(struct inode *inode)
>  {
> -	struct inode *inode = file->f_mapping->host;
>  	unsigned int i_flags;
>  	unsigned int flags = 0;
>  
>  	i_flags = inode->i_flags;
>  	if (i_flags & S_IMMUTABLE)
>  		flags |= FS_IMMUTABLE_FL;
> +	return flags;
> +}
> +
> +static int
> +efivarfs_ioc_getxflags(struct file *file, void __user *arg)
> +{
> +	struct inode *inode = file->f_mapping->host;
> +	unsigned int flags = efivarfs_getflags(inode);
>  
>  	if (copy_to_user(arg, &flags, sizeof(flags)))
>  		return -EFAULT;
> @@ -132,6 +138,7 @@ efivarfs_ioc_setxflags(struct file *file, void __user *arg)
>  	struct inode *inode = file->f_mapping->host;
>  	unsigned int flags;
>  	unsigned int i_flags = 0;
> +	unsigned int oldflags = efivarfs_getflags(inode);
>  	int error;
>  
>  	if (!inode_owner_or_capable(inode))
> @@ -143,8 +150,9 @@ efivarfs_ioc_setxflags(struct file *file, void __user *arg)
>  	if (flags & ~FS_IMMUTABLE_FL)
>  		return -EOPNOTSUPP;
>  
> -	if (!capable(CAP_LINUX_IMMUTABLE))
> -		return -EPERM;
> +	error = vfs_ioc_setflags_check(inode, oldflags, flags);
> +	if (error)
> +		return error;
>  
>  	if (flags & FS_IMMUTABLE_FL)
>  		i_flags |= S_IMMUTABLE;
> diff --git a/fs/ext2/ioctl.c b/fs/ext2/ioctl.c
> index 0367c0039e68..88b3b9720023 100644
> --- a/fs/ext2/ioctl.c
> +++ b/fs/ext2/ioctl.c
> @@ -60,18 +60,10 @@ long ext2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
>  		}
>  		oldflags = ei->i_flags;
>  
> -		/*
> -		 * The IMMUTABLE and APPEND_ONLY flags can only be changed by
> -		 * the relevant capability.
> -		 *
> -		 * This test looks nicer. Thanks to Pauline Middelink
> -		 */
> -		if ((flags ^ oldflags) & (EXT2_APPEND_FL | EXT2_IMMUTABLE_FL)) {
> -			if (!capable(CAP_LINUX_IMMUTABLE)) {
> -				inode_unlock(inode);
> -				ret = -EPERM;
> -				goto setflags_out;
> -			}
> +		ret = vfs_ioc_setflags_check(inode, oldflags, flags);
> +		if (ret) {
> +			inode_unlock(inode);
> +			goto setflags_out;
>  		}
>  
>  		flags = flags & EXT2_FL_USER_MODIFIABLE;
> diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
> index e486e49b31ed..5126ee351a84 100644
> --- a/fs/ext4/ioctl.c
> +++ b/fs/ext4/ioctl.c
> @@ -289,16 +289,9 @@ static int ext4_ioctl_setflags(struct inode *inode,
>  	/* The JOURNAL_DATA flag is modifiable only by root */
>  	jflag = flags & EXT4_JOURNAL_DATA_FL;
>  
> -	/*
> -	 * The IMMUTABLE and APPEND_ONLY flags can only be changed by
> -	 * the relevant capability.
> -	 *
> -	 * This test looks nicer. Thanks to Pauline Middelink
> -	 */
> -	if ((flags ^ oldflags) & (EXT4_APPEND_FL | EXT4_IMMUTABLE_FL)) {
> -		if (!capable(CAP_LINUX_IMMUTABLE))
> -			goto flags_out;
> -	}
> +	err = vfs_ioc_setflags_check(inode, oldflags, flags);
> +	if (err)
> +		goto flags_out;
>  
>  	/*
>  	 * The JOURNAL_DATA flag can only be changed by
> diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
> index 45b45f37d347..a969d5497e03 100644
> --- a/fs/f2fs/file.c
> +++ b/fs/f2fs/file.c
> @@ -1670,6 +1670,7 @@ static int __f2fs_ioc_setflags(struct inode *inode, unsigned int flags)
>  {
>  	struct f2fs_inode_info *fi = F2FS_I(inode);
>  	unsigned int oldflags;
> +	int err;
>  
>  	/* Is it quota file? Do not allow user to mess with it */
>  	if (IS_NOQUOTA(inode))
> @@ -1679,9 +1680,9 @@ static int __f2fs_ioc_setflags(struct inode *inode, unsigned int flags)
>  
>  	oldflags = fi->i_flags;
>  
> -	if ((flags ^ oldflags) & (F2FS_APPEND_FL | F2FS_IMMUTABLE_FL))
> -		if (!capable(CAP_LINUX_IMMUTABLE))
> -			return -EPERM;
> +	err = vfs_ioc_setflags_check(inode, oldflags, flags);
> +	if (err)
> +		return err;
>  
>  	flags = flags & F2FS_FL_USER_MODIFIABLE;
>  	flags |= oldflags & ~F2FS_FL_USER_MODIFIABLE;
> diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c
> index d174b1f8fd08..99f53cf699c6 100644
> --- a/fs/gfs2/file.c
> +++ b/fs/gfs2/file.c
> @@ -136,27 +136,36 @@ static struct {
>  	{FS_JOURNAL_DATA_FL, GFS2_DIF_JDATA | GFS2_DIF_INHERIT_JDATA},
>  };
>  
> +static inline u32 gfs2_gfsflags_to_fsflags(struct inode *inode, u32 gfsflags)
> +{
> +	int i;
> +	u32 fsflags = 0;
> +
> +	if (S_ISDIR(inode->i_mode))
> +		gfsflags &= ~GFS2_DIF_JDATA;
> +	else
> +		gfsflags &= ~GFS2_DIF_INHERIT_JDATA;
> +
> +	for (i = 0; i < ARRAY_SIZE(fsflag_gfs2flag); i++)
> +		if (gfsflags & fsflag_gfs2flag[i].gfsflag)
> +			fsflags |= fsflag_gfs2flag[i].fsflag;
> +	return fsflags;
> +}
> +
>  static int gfs2_get_flags(struct file *filp, u32 __user *ptr)
>  {
>  	struct inode *inode = file_inode(filp);
>  	struct gfs2_inode *ip = GFS2_I(inode);
>  	struct gfs2_holder gh;
> -	int i, error;
> -	u32 gfsflags, fsflags = 0;
> +	int error;
> +	u32 fsflags;
>  
>  	gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &gh);
>  	error = gfs2_glock_nq(&gh);
>  	if (error)
>  		goto out_uninit;
>  
> -	gfsflags = ip->i_diskflags;
> -	if (S_ISDIR(inode->i_mode))
> -		gfsflags &= ~GFS2_DIF_JDATA;
> -	else
> -		gfsflags &= ~GFS2_DIF_INHERIT_JDATA;
> -	for (i = 0; i < ARRAY_SIZE(fsflag_gfs2flag); i++)
> -		if (gfsflags & fsflag_gfs2flag[i].gfsflag)
> -			fsflags |= fsflag_gfs2flag[i].fsflag;
> +	fsflags = gfs2_gfsflags_to_fsflags(inode, ip->i_diskflags);
>  
>  	if (put_user(fsflags, ptr))
>  		error = -EFAULT;
> @@ -200,9 +209,11 @@ void gfs2_set_inode_flags(struct inode *inode)
>   * @filp: file pointer
>   * @reqflags: The flags to set
>   * @mask: Indicates which flags are valid
> + * @fsflags: The FS_* inode flags passed in
>   *
>   */
> -static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask)
> +static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask,
> +			     const u32 fsflags)
>  {
>  	struct inode *inode = file_inode(filp);
>  	struct gfs2_inode *ip = GFS2_I(inode);
> @@ -210,7 +221,7 @@ static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask)
>  	struct buffer_head *bh;
>  	struct gfs2_holder gh;
>  	int error;
> -	u32 new_flags, flags;
> +	u32 new_flags, flags, oldflags;
>  
>  	error = mnt_want_write_file(filp);
>  	if (error)
> @@ -220,6 +231,11 @@ static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask)
>  	if (error)
>  		goto out_drop_write;
>  
> +	oldflags = gfs2_gfsflags_to_fsflags(inode, ip->i_diskflags);
> +	error = vfs_ioc_setflags_check(inode, oldflags, fsflags);
> +	if (error)
> +		goto out;
> +
>  	error = -EACCES;
>  	if (!inode_owner_or_capable(inode))
>  		goto out;
> @@ -308,7 +324,7 @@ static int gfs2_set_flags(struct file *filp, u32 __user *ptr)
>  		mask &= ~(GFS2_DIF_TOPDIR | GFS2_DIF_INHERIT_JDATA);
>  	}
>  
> -	return do_gfs2_set_flags(filp, gfsflags, mask);
> +	return do_gfs2_set_flags(filp, gfsflags, mask, fsflags);
>  }
>  
>  static int gfs2_getlabel(struct file *filp, char __user *label)
> diff --git a/fs/hfsplus/ioctl.c b/fs/hfsplus/ioctl.c
> index 5e6502ef7415..862a3c9481d7 100644
> --- a/fs/hfsplus/ioctl.c
> +++ b/fs/hfsplus/ioctl.c
> @@ -57,9 +57,8 @@ static int hfsplus_ioctl_bless(struct file *file, int __user *user_flags)
>  	return 0;
>  }
>  
> -static int hfsplus_ioctl_getflags(struct file *file, int __user *user_flags)
> +static inline unsigned int hfsplus_getflags(struct inode *inode)
>  {
> -	struct inode *inode = file_inode(file);
>  	struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
>  	unsigned int flags = 0;
>  
> @@ -69,6 +68,13 @@ static int hfsplus_ioctl_getflags(struct file *file, int __user *user_flags)
>  		flags |= FS_APPEND_FL;
>  	if (hip->userflags & HFSPLUS_FLG_NODUMP)
>  		flags |= FS_NODUMP_FL;
> +	return flags;
> +}
> +
> +static int hfsplus_ioctl_getflags(struct file *file, int __user *user_flags)
> +{
> +	struct inode *inode = file_inode(file);
> +	unsigned int flags = hfsplus_getflags(inode);
>  
>  	return put_user(flags, user_flags);
>  }
> @@ -78,6 +84,7 @@ static int hfsplus_ioctl_setflags(struct file *file, int __user *user_flags)
>  	struct inode *inode = file_inode(file);
>  	struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
>  	unsigned int flags, new_fl = 0;
> +	unsigned int oldflags = hfsplus_getflags(inode);
>  	int err = 0;
>  
>  	err = mnt_want_write_file(file);
> @@ -96,13 +103,9 @@ static int hfsplus_ioctl_setflags(struct file *file, int __user *user_flags)
>  
>  	inode_lock(inode);
>  
> -	if ((flags & (FS_IMMUTABLE_FL|FS_APPEND_FL)) ||
> -	    inode->i_flags & (S_IMMUTABLE|S_APPEND)) {
> -		if (!capable(CAP_LINUX_IMMUTABLE)) {
> -			err = -EPERM;
> -			goto out_unlock_inode;
> -		}
> -	}
> +	err = vfs_ioc_setflags_check(inode, oldflags, flags);
> +	if (err)
> +		goto out_unlock_inode;
>  
>  	/* don't silently ignore unsupported ext2 flags */
>  	if (flags & ~(FS_IMMUTABLE_FL|FS_APPEND_FL|FS_NODUMP_FL)) {
> diff --git a/fs/inode.c b/fs/inode.c
> index df6542ec3b88..0ce60b720608 100644
> --- a/fs/inode.c
> +++ b/fs/inode.c
> @@ -2170,3 +2170,20 @@ struct timespec64 current_time(struct inode *inode)
>  	return timespec64_trunc(now, inode->i_sb->s_time_gran);
>  }
>  EXPORT_SYMBOL(current_time);
> +
> +/* Generic function to check FS_IOC_SETFLAGS values. */
> +int vfs_ioc_setflags_check(struct inode *inode, int oldflags, int flags)
> +{
> +	/*
> +	 * The IMMUTABLE and APPEND_ONLY flags can only be changed by
> +	 * the relevant capability.
> +	 *
> +	 * This test looks nicer. Thanks to Pauline Middelink
> +	 */
> +	if ((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL) &&
> +	    !capable(CAP_LINUX_IMMUTABLE))
> +		return -EPERM;
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(vfs_ioc_setflags_check);
> diff --git a/fs/jfs/ioctl.c b/fs/jfs/ioctl.c
> index ba34dae8bd9f..b485c2d7620f 100644
> --- a/fs/jfs/ioctl.c
> +++ b/fs/jfs/ioctl.c
> @@ -98,24 +98,16 @@ long jfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
>  		/* Lock against other parallel changes of flags */
>  		inode_lock(inode);
>  
> -		oldflags = jfs_inode->mode2;
> -
> -		/*
> -		 * The IMMUTABLE and APPEND_ONLY flags can only be changed by
> -		 * the relevant capability.
> -		 */
> -		if ((oldflags & JFS_IMMUTABLE_FL) ||
> -			((flags ^ oldflags) &
> -			(JFS_APPEND_FL | JFS_IMMUTABLE_FL))) {
> -			if (!capable(CAP_LINUX_IMMUTABLE)) {
> -				inode_unlock(inode);
> -				err = -EPERM;
> -				goto setflags_out;
> -			}
> +		oldflags = jfs_map_ext2(jfs_inode->mode2 & JFS_FL_USER_VISIBLE,
> +					0);
> +		err = vfs_ioc_setflags_check(inode, oldflags, flags);
> +		if (err) {
> +			inode_unlock(inode);
> +			goto setflags_out;
>  		}
>  
>  		flags = flags & JFS_FL_USER_MODIFIABLE;
> -		flags |= oldflags & ~JFS_FL_USER_MODIFIABLE;
> +		flags |= jfs_inode->mode2 & ~JFS_FL_USER_MODIFIABLE;
>  		jfs_inode->mode2 = flags;
>  
>  		jfs_set_inode_flags(inode);
> diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c
> index 9b96d79eea6c..0632336d2515 100644
> --- a/fs/nilfs2/ioctl.c
> +++ b/fs/nilfs2/ioctl.c
> @@ -148,13 +148,8 @@ static int nilfs_ioctl_setflags(struct inode *inode, struct file *filp,
>  
>  	oldflags = NILFS_I(inode)->i_flags;
>  
> -	/*
> -	 * The IMMUTABLE and APPEND_ONLY flags can only be changed by the
> -	 * relevant capability.
> -	 */
> -	ret = -EPERM;
> -	if (((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL)) &&
> -	    !capable(CAP_LINUX_IMMUTABLE))
> +	ret = vfs_ioc_setflags_check(inode, oldflags, flags);
> +	if (ret)
>  		goto out;
>  
>  	ret = nilfs_transaction_begin(inode->i_sb, &ti, 0);
> diff --git a/fs/ocfs2/ioctl.c b/fs/ocfs2/ioctl.c
> index 994726ada857..467a2faf0305 100644
> --- a/fs/ocfs2/ioctl.c
> +++ b/fs/ocfs2/ioctl.c
> @@ -106,16 +106,9 @@ static int ocfs2_set_inode_attr(struct inode *inode, unsigned flags,
>  	flags = flags & mask;
>  	flags |= oldflags & ~mask;
>  
> -	/*
> -	 * The IMMUTABLE and APPEND_ONLY flags can only be changed by
> -	 * the relevant capability.
> -	 */
> -	status = -EPERM;
> -	if ((oldflags & OCFS2_IMMUTABLE_FL) || ((flags ^ oldflags) &
> -		(OCFS2_APPEND_FL | OCFS2_IMMUTABLE_FL))) {
> -		if (!capable(CAP_LINUX_IMMUTABLE))
> -			goto bail_unlock;
> -	}
> +	status = vfs_ioc_setflags_check(inode, oldflags, flags);
> +	if (status)
> +		goto bail_unlock;
>  
>  	handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);
>  	if (IS_ERR(handle)) {
> diff --git a/fs/reiserfs/ioctl.c b/fs/reiserfs/ioctl.c
> index acbbaf7a0bb2..92bcb1ecd994 100644
> --- a/fs/reiserfs/ioctl.c
> +++ b/fs/reiserfs/ioctl.c
> @@ -74,13 +74,11 @@ long reiserfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
>  				err = -EPERM;
>  				goto setflags_out;
>  			}
> -			if (((flags ^ REISERFS_I(inode)->
> -			      i_attrs) & (REISERFS_IMMUTABLE_FL |
> -					  REISERFS_APPEND_FL))
> -			    && !capable(CAP_LINUX_IMMUTABLE)) {
> -				err = -EPERM;
> +			err = vfs_ioc_setflags_check(inode,
> +						     REISERFS_I(inode)->i_attrs,
> +						     flags);
> +			if (err)
>  				goto setflags_out;
> -			}
>  			if ((flags & REISERFS_NOTAIL_FL) &&
>  			    S_ISREG(inode->i_mode)) {
>  				int result;
> diff --git a/fs/ubifs/ioctl.c b/fs/ubifs/ioctl.c
> index 4f1a397fda69..bdea836fc38b 100644
> --- a/fs/ubifs/ioctl.c
> +++ b/fs/ubifs/ioctl.c
> @@ -107,18 +107,11 @@ static int setflags(struct inode *inode, int flags)
>  	if (err)
>  		return err;
>  
> -	/*
> -	 * The IMMUTABLE and APPEND_ONLY flags can only be changed by
> -	 * the relevant capability.
> -	 */
>  	mutex_lock(&ui->ui_mutex);
>  	oldflags = ubifs2ioctl(ui->flags);
> -	if ((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL)) {
> -		if (!capable(CAP_LINUX_IMMUTABLE)) {
> -			err = -EPERM;
> -			goto out_unlock;
> -		}
> -	}
> +	err = vfs_ioc_setflags_check(inode, oldflags, flags);
> +	if (err)
> +		goto out_unlock;
>  
>  	ui->flags = ioctl2ubifs(flags);
>  	ubifs_set_inode_flags(inode);
> diff --git a/include/linux/fs.h b/include/linux/fs.h
> index f7fdfe93e25d..1825d055808c 100644
> --- a/include/linux/fs.h
> +++ b/include/linux/fs.h
> @@ -3546,4 +3546,6 @@ static inline struct sock *io_uring_get_socket(struct file *file)
>  }
>  #endif
>  
> +int vfs_ioc_setflags_check(struct inode *inode, int oldflags, int flags);
> +
>  #endif /* _LINUX_FS_H */
> 
-- 
Jan Kara <jack@suse.com>
SUSE Labs, CR

^ permalink raw reply

* [PATCH v5 7/7] i2c: core: Tidy up handling of init_irq
From: Charles Keepax @ 2019-06-20 13:34 UTC (permalink / raw)
  To: wsa, mika.westerberg
  Cc: jarkko.nikula, andriy.shevchenko, linux-i2c, linux-acpi,
	linux-kernel, benjamin.tissoires, jbroadus, patches
In-Reply-To: <20190620133420.4632-1-ckeepax@opensource.cirrus.com>

Only set init_irq during i2c_device_new and only handle client->irq on
the probe/remove paths.

Suggested-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
---

No changes since v4.

Thanks,
Charles

 drivers/i2c/i2c-core-base.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c
index 95a0380286c1c..a3dbaefe4ca66 100644
--- a/drivers/i2c/i2c-core-base.c
+++ b/drivers/i2c/i2c-core-base.c
@@ -314,6 +314,8 @@ static int i2c_device_probe(struct device *dev)
 
 	driver = to_i2c_driver(dev->driver);
 
+	client->irq = client->init_irq;
+
 	if (!client->irq && !driver->disable_i2c_core_irq_mapping) {
 		int irq = -ENOENT;
 
@@ -424,7 +426,7 @@ static int i2c_device_remove(struct device *dev)
 	dev_pm_clear_wake_irq(&client->dev);
 	device_init_wakeup(&client->dev, false);
 
-	client->irq = client->init_irq;
+	client->irq = 0;
 	if (client->flags & I2C_CLIENT_HOST_NOTIFY)
 		pm_runtime_put(&client->adapter->dev);
 
@@ -741,7 +743,6 @@ i2c_new_client_device(struct i2c_adapter *adap, struct i2c_board_info const *inf
 	if (!client->init_irq)
 		client->init_irq = i2c_dev_irq_from_resources(info->resources,
 							 info->num_resources);
-	client->irq = client->init_irq;
 
 	strlcpy(client->name, info->type, sizeof(client->name));
 
-- 
2.11.0

^ permalink raw reply related

* [Cluster-devel] [PATCH v2 1/4] vfs: create a generic checking function for FS_IOC_SETFLAGS
From: Jan Kara @ 2019-06-20 13:34 UTC (permalink / raw)
  To: cluster-devel.redhat.com
In-Reply-To: <20190612004258.GX1871505@magnolia>

On Tue 11-06-19 17:42:58, Darrick J. Wong wrote:
> From: Darrick J. Wong <darrick.wong@oracle.com>
> 
> Create a generic checking function for the incoming FS_IOC_SETFLAGS flag
> values so that we can standardize the implementations that follow ext4's
> flag values.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>

The patch looks good to me. You can add:

Reviewed-by: Jan Kara <jack@suse.cz>

								Honza

> ---
> v2: fix jfs locking and remove its opencoded flags check
> ---
>  fs/btrfs/ioctl.c    |   13 +++++--------
>  fs/efivarfs/file.c  |   18 +++++++++++++-----
>  fs/ext2/ioctl.c     |   16 ++++------------
>  fs/ext4/ioctl.c     |   13 +++----------
>  fs/f2fs/file.c      |    7 ++++---
>  fs/gfs2/file.c      |   42 +++++++++++++++++++++++++++++-------------
>  fs/hfsplus/ioctl.c  |   21 ++++++++++++---------
>  fs/inode.c          |   17 +++++++++++++++++
>  fs/jfs/ioctl.c      |   22 +++++++---------------
>  fs/nilfs2/ioctl.c   |    9 ++-------
>  fs/ocfs2/ioctl.c    |   13 +++----------
>  fs/reiserfs/ioctl.c |   10 ++++------
>  fs/ubifs/ioctl.c    |   13 +++----------
>  include/linux/fs.h  |    2 ++
>  14 files changed, 108 insertions(+), 108 deletions(-)
> 
> diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
> index 6dafa857bbb9..f408aa93b0cf 100644
> --- a/fs/btrfs/ioctl.c
> +++ b/fs/btrfs/ioctl.c
> @@ -187,7 +187,7 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
>  	struct btrfs_inode *binode = BTRFS_I(inode);
>  	struct btrfs_root *root = binode->root;
>  	struct btrfs_trans_handle *trans;
> -	unsigned int fsflags;
> +	unsigned int fsflags, old_fsflags;
>  	int ret;
>  	const char *comp = NULL;
>  	u32 binode_flags = binode->flags;
> @@ -212,13 +212,10 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
>  	inode_lock(inode);
>  
>  	fsflags = btrfs_mask_fsflags_for_type(inode, fsflags);
> -	if ((fsflags ^ btrfs_inode_flags_to_fsflags(binode->flags)) &
> -	    (FS_APPEND_FL | FS_IMMUTABLE_FL)) {
> -		if (!capable(CAP_LINUX_IMMUTABLE)) {
> -			ret = -EPERM;
> -			goto out_unlock;
> -		}
> -	}
> +	old_fsflags = btrfs_inode_flags_to_fsflags(binode->flags);
> +	ret = vfs_ioc_setflags_check(inode, old_fsflags, fsflags);
> +	if (ret)
> +		goto out_unlock;
>  
>  	if (fsflags & FS_SYNC_FL)
>  		binode_flags |= BTRFS_INODE_SYNC;
> diff --git a/fs/efivarfs/file.c b/fs/efivarfs/file.c
> index 8e568428c88b..f4f6c1bec132 100644
> --- a/fs/efivarfs/file.c
> +++ b/fs/efivarfs/file.c
> @@ -110,16 +110,22 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf,
>  	return size;
>  }
>  
> -static int
> -efivarfs_ioc_getxflags(struct file *file, void __user *arg)
> +static inline unsigned int efivarfs_getflags(struct inode *inode)
>  {
> -	struct inode *inode = file->f_mapping->host;
>  	unsigned int i_flags;
>  	unsigned int flags = 0;
>  
>  	i_flags = inode->i_flags;
>  	if (i_flags & S_IMMUTABLE)
>  		flags |= FS_IMMUTABLE_FL;
> +	return flags;
> +}
> +
> +static int
> +efivarfs_ioc_getxflags(struct file *file, void __user *arg)
> +{
> +	struct inode *inode = file->f_mapping->host;
> +	unsigned int flags = efivarfs_getflags(inode);
>  
>  	if (copy_to_user(arg, &flags, sizeof(flags)))
>  		return -EFAULT;
> @@ -132,6 +138,7 @@ efivarfs_ioc_setxflags(struct file *file, void __user *arg)
>  	struct inode *inode = file->f_mapping->host;
>  	unsigned int flags;
>  	unsigned int i_flags = 0;
> +	unsigned int oldflags = efivarfs_getflags(inode);
>  	int error;
>  
>  	if (!inode_owner_or_capable(inode))
> @@ -143,8 +150,9 @@ efivarfs_ioc_setxflags(struct file *file, void __user *arg)
>  	if (flags & ~FS_IMMUTABLE_FL)
>  		return -EOPNOTSUPP;
>  
> -	if (!capable(CAP_LINUX_IMMUTABLE))
> -		return -EPERM;
> +	error = vfs_ioc_setflags_check(inode, oldflags, flags);
> +	if (error)
> +		return error;
>  
>  	if (flags & FS_IMMUTABLE_FL)
>  		i_flags |= S_IMMUTABLE;
> diff --git a/fs/ext2/ioctl.c b/fs/ext2/ioctl.c
> index 0367c0039e68..88b3b9720023 100644
> --- a/fs/ext2/ioctl.c
> +++ b/fs/ext2/ioctl.c
> @@ -60,18 +60,10 @@ long ext2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
>  		}
>  		oldflags = ei->i_flags;
>  
> -		/*
> -		 * The IMMUTABLE and APPEND_ONLY flags can only be changed by
> -		 * the relevant capability.
> -		 *
> -		 * This test looks nicer. Thanks to Pauline Middelink
> -		 */
> -		if ((flags ^ oldflags) & (EXT2_APPEND_FL | EXT2_IMMUTABLE_FL)) {
> -			if (!capable(CAP_LINUX_IMMUTABLE)) {
> -				inode_unlock(inode);
> -				ret = -EPERM;
> -				goto setflags_out;
> -			}
> +		ret = vfs_ioc_setflags_check(inode, oldflags, flags);
> +		if (ret) {
> +			inode_unlock(inode);
> +			goto setflags_out;
>  		}
>  
>  		flags = flags & EXT2_FL_USER_MODIFIABLE;
> diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
> index e486e49b31ed..5126ee351a84 100644
> --- a/fs/ext4/ioctl.c
> +++ b/fs/ext4/ioctl.c
> @@ -289,16 +289,9 @@ static int ext4_ioctl_setflags(struct inode *inode,
>  	/* The JOURNAL_DATA flag is modifiable only by root */
>  	jflag = flags & EXT4_JOURNAL_DATA_FL;
>  
> -	/*
> -	 * The IMMUTABLE and APPEND_ONLY flags can only be changed by
> -	 * the relevant capability.
> -	 *
> -	 * This test looks nicer. Thanks to Pauline Middelink
> -	 */
> -	if ((flags ^ oldflags) & (EXT4_APPEND_FL | EXT4_IMMUTABLE_FL)) {
> -		if (!capable(CAP_LINUX_IMMUTABLE))
> -			goto flags_out;
> -	}
> +	err = vfs_ioc_setflags_check(inode, oldflags, flags);
> +	if (err)
> +		goto flags_out;
>  
>  	/*
>  	 * The JOURNAL_DATA flag can only be changed by
> diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
> index 45b45f37d347..a969d5497e03 100644
> --- a/fs/f2fs/file.c
> +++ b/fs/f2fs/file.c
> @@ -1670,6 +1670,7 @@ static int __f2fs_ioc_setflags(struct inode *inode, unsigned int flags)
>  {
>  	struct f2fs_inode_info *fi = F2FS_I(inode);
>  	unsigned int oldflags;
> +	int err;
>  
>  	/* Is it quota file? Do not allow user to mess with it */
>  	if (IS_NOQUOTA(inode))
> @@ -1679,9 +1680,9 @@ static int __f2fs_ioc_setflags(struct inode *inode, unsigned int flags)
>  
>  	oldflags = fi->i_flags;
>  
> -	if ((flags ^ oldflags) & (F2FS_APPEND_FL | F2FS_IMMUTABLE_FL))
> -		if (!capable(CAP_LINUX_IMMUTABLE))
> -			return -EPERM;
> +	err = vfs_ioc_setflags_check(inode, oldflags, flags);
> +	if (err)
> +		return err;
>  
>  	flags = flags & F2FS_FL_USER_MODIFIABLE;
>  	flags |= oldflags & ~F2FS_FL_USER_MODIFIABLE;
> diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c
> index d174b1f8fd08..99f53cf699c6 100644
> --- a/fs/gfs2/file.c
> +++ b/fs/gfs2/file.c
> @@ -136,27 +136,36 @@ static struct {
>  	{FS_JOURNAL_DATA_FL, GFS2_DIF_JDATA | GFS2_DIF_INHERIT_JDATA},
>  };
>  
> +static inline u32 gfs2_gfsflags_to_fsflags(struct inode *inode, u32 gfsflags)
> +{
> +	int i;
> +	u32 fsflags = 0;
> +
> +	if (S_ISDIR(inode->i_mode))
> +		gfsflags &= ~GFS2_DIF_JDATA;
> +	else
> +		gfsflags &= ~GFS2_DIF_INHERIT_JDATA;
> +
> +	for (i = 0; i < ARRAY_SIZE(fsflag_gfs2flag); i++)
> +		if (gfsflags & fsflag_gfs2flag[i].gfsflag)
> +			fsflags |= fsflag_gfs2flag[i].fsflag;
> +	return fsflags;
> +}
> +
>  static int gfs2_get_flags(struct file *filp, u32 __user *ptr)
>  {
>  	struct inode *inode = file_inode(filp);
>  	struct gfs2_inode *ip = GFS2_I(inode);
>  	struct gfs2_holder gh;
> -	int i, error;
> -	u32 gfsflags, fsflags = 0;
> +	int error;
> +	u32 fsflags;
>  
>  	gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &gh);
>  	error = gfs2_glock_nq(&gh);
>  	if (error)
>  		goto out_uninit;
>  
> -	gfsflags = ip->i_diskflags;
> -	if (S_ISDIR(inode->i_mode))
> -		gfsflags &= ~GFS2_DIF_JDATA;
> -	else
> -		gfsflags &= ~GFS2_DIF_INHERIT_JDATA;
> -	for (i = 0; i < ARRAY_SIZE(fsflag_gfs2flag); i++)
> -		if (gfsflags & fsflag_gfs2flag[i].gfsflag)
> -			fsflags |= fsflag_gfs2flag[i].fsflag;
> +	fsflags = gfs2_gfsflags_to_fsflags(inode, ip->i_diskflags);
>  
>  	if (put_user(fsflags, ptr))
>  		error = -EFAULT;
> @@ -200,9 +209,11 @@ void gfs2_set_inode_flags(struct inode *inode)
>   * @filp: file pointer
>   * @reqflags: The flags to set
>   * @mask: Indicates which flags are valid
> + * @fsflags: The FS_* inode flags passed in
>   *
>   */
> -static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask)
> +static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask,
> +			     const u32 fsflags)
>  {
>  	struct inode *inode = file_inode(filp);
>  	struct gfs2_inode *ip = GFS2_I(inode);
> @@ -210,7 +221,7 @@ static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask)
>  	struct buffer_head *bh;
>  	struct gfs2_holder gh;
>  	int error;
> -	u32 new_flags, flags;
> +	u32 new_flags, flags, oldflags;
>  
>  	error = mnt_want_write_file(filp);
>  	if (error)
> @@ -220,6 +231,11 @@ static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask)
>  	if (error)
>  		goto out_drop_write;
>  
> +	oldflags = gfs2_gfsflags_to_fsflags(inode, ip->i_diskflags);
> +	error = vfs_ioc_setflags_check(inode, oldflags, fsflags);
> +	if (error)
> +		goto out;
> +
>  	error = -EACCES;
>  	if (!inode_owner_or_capable(inode))
>  		goto out;
> @@ -308,7 +324,7 @@ static int gfs2_set_flags(struct file *filp, u32 __user *ptr)
>  		mask &= ~(GFS2_DIF_TOPDIR | GFS2_DIF_INHERIT_JDATA);
>  	}
>  
> -	return do_gfs2_set_flags(filp, gfsflags, mask);
> +	return do_gfs2_set_flags(filp, gfsflags, mask, fsflags);
>  }
>  
>  static int gfs2_getlabel(struct file *filp, char __user *label)
> diff --git a/fs/hfsplus/ioctl.c b/fs/hfsplus/ioctl.c
> index 5e6502ef7415..862a3c9481d7 100644
> --- a/fs/hfsplus/ioctl.c
> +++ b/fs/hfsplus/ioctl.c
> @@ -57,9 +57,8 @@ static int hfsplus_ioctl_bless(struct file *file, int __user *user_flags)
>  	return 0;
>  }
>  
> -static int hfsplus_ioctl_getflags(struct file *file, int __user *user_flags)
> +static inline unsigned int hfsplus_getflags(struct inode *inode)
>  {
> -	struct inode *inode = file_inode(file);
>  	struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
>  	unsigned int flags = 0;
>  
> @@ -69,6 +68,13 @@ static int hfsplus_ioctl_getflags(struct file *file, int __user *user_flags)
>  		flags |= FS_APPEND_FL;
>  	if (hip->userflags & HFSPLUS_FLG_NODUMP)
>  		flags |= FS_NODUMP_FL;
> +	return flags;
> +}
> +
> +static int hfsplus_ioctl_getflags(struct file *file, int __user *user_flags)
> +{
> +	struct inode *inode = file_inode(file);
> +	unsigned int flags = hfsplus_getflags(inode);
>  
>  	return put_user(flags, user_flags);
>  }
> @@ -78,6 +84,7 @@ static int hfsplus_ioctl_setflags(struct file *file, int __user *user_flags)
>  	struct inode *inode = file_inode(file);
>  	struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
>  	unsigned int flags, new_fl = 0;
> +	unsigned int oldflags = hfsplus_getflags(inode);
>  	int err = 0;
>  
>  	err = mnt_want_write_file(file);
> @@ -96,13 +103,9 @@ static int hfsplus_ioctl_setflags(struct file *file, int __user *user_flags)
>  
>  	inode_lock(inode);
>  
> -	if ((flags & (FS_IMMUTABLE_FL|FS_APPEND_FL)) ||
> -	    inode->i_flags & (S_IMMUTABLE|S_APPEND)) {
> -		if (!capable(CAP_LINUX_IMMUTABLE)) {
> -			err = -EPERM;
> -			goto out_unlock_inode;
> -		}
> -	}
> +	err = vfs_ioc_setflags_check(inode, oldflags, flags);
> +	if (err)
> +		goto out_unlock_inode;
>  
>  	/* don't silently ignore unsupported ext2 flags */
>  	if (flags & ~(FS_IMMUTABLE_FL|FS_APPEND_FL|FS_NODUMP_FL)) {
> diff --git a/fs/inode.c b/fs/inode.c
> index df6542ec3b88..0ce60b720608 100644
> --- a/fs/inode.c
> +++ b/fs/inode.c
> @@ -2170,3 +2170,20 @@ struct timespec64 current_time(struct inode *inode)
>  	return timespec64_trunc(now, inode->i_sb->s_time_gran);
>  }
>  EXPORT_SYMBOL(current_time);
> +
> +/* Generic function to check FS_IOC_SETFLAGS values. */
> +int vfs_ioc_setflags_check(struct inode *inode, int oldflags, int flags)
> +{
> +	/*
> +	 * The IMMUTABLE and APPEND_ONLY flags can only be changed by
> +	 * the relevant capability.
> +	 *
> +	 * This test looks nicer. Thanks to Pauline Middelink
> +	 */
> +	if ((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL) &&
> +	    !capable(CAP_LINUX_IMMUTABLE))
> +		return -EPERM;
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(vfs_ioc_setflags_check);
> diff --git a/fs/jfs/ioctl.c b/fs/jfs/ioctl.c
> index ba34dae8bd9f..b485c2d7620f 100644
> --- a/fs/jfs/ioctl.c
> +++ b/fs/jfs/ioctl.c
> @@ -98,24 +98,16 @@ long jfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
>  		/* Lock against other parallel changes of flags */
>  		inode_lock(inode);
>  
> -		oldflags = jfs_inode->mode2;
> -
> -		/*
> -		 * The IMMUTABLE and APPEND_ONLY flags can only be changed by
> -		 * the relevant capability.
> -		 */
> -		if ((oldflags & JFS_IMMUTABLE_FL) ||
> -			((flags ^ oldflags) &
> -			(JFS_APPEND_FL | JFS_IMMUTABLE_FL))) {
> -			if (!capable(CAP_LINUX_IMMUTABLE)) {
> -				inode_unlock(inode);
> -				err = -EPERM;
> -				goto setflags_out;
> -			}
> +		oldflags = jfs_map_ext2(jfs_inode->mode2 & JFS_FL_USER_VISIBLE,
> +					0);
> +		err = vfs_ioc_setflags_check(inode, oldflags, flags);
> +		if (err) {
> +			inode_unlock(inode);
> +			goto setflags_out;
>  		}
>  
>  		flags = flags & JFS_FL_USER_MODIFIABLE;
> -		flags |= oldflags & ~JFS_FL_USER_MODIFIABLE;
> +		flags |= jfs_inode->mode2 & ~JFS_FL_USER_MODIFIABLE;
>  		jfs_inode->mode2 = flags;
>  
>  		jfs_set_inode_flags(inode);
> diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c
> index 9b96d79eea6c..0632336d2515 100644
> --- a/fs/nilfs2/ioctl.c
> +++ b/fs/nilfs2/ioctl.c
> @@ -148,13 +148,8 @@ static int nilfs_ioctl_setflags(struct inode *inode, struct file *filp,
>  
>  	oldflags = NILFS_I(inode)->i_flags;
>  
> -	/*
> -	 * The IMMUTABLE and APPEND_ONLY flags can only be changed by the
> -	 * relevant capability.
> -	 */
> -	ret = -EPERM;
> -	if (((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL)) &&
> -	    !capable(CAP_LINUX_IMMUTABLE))
> +	ret = vfs_ioc_setflags_check(inode, oldflags, flags);
> +	if (ret)
>  		goto out;
>  
>  	ret = nilfs_transaction_begin(inode->i_sb, &ti, 0);
> diff --git a/fs/ocfs2/ioctl.c b/fs/ocfs2/ioctl.c
> index 994726ada857..467a2faf0305 100644
> --- a/fs/ocfs2/ioctl.c
> +++ b/fs/ocfs2/ioctl.c
> @@ -106,16 +106,9 @@ static int ocfs2_set_inode_attr(struct inode *inode, unsigned flags,
>  	flags = flags & mask;
>  	flags |= oldflags & ~mask;
>  
> -	/*
> -	 * The IMMUTABLE and APPEND_ONLY flags can only be changed by
> -	 * the relevant capability.
> -	 */
> -	status = -EPERM;
> -	if ((oldflags & OCFS2_IMMUTABLE_FL) || ((flags ^ oldflags) &
> -		(OCFS2_APPEND_FL | OCFS2_IMMUTABLE_FL))) {
> -		if (!capable(CAP_LINUX_IMMUTABLE))
> -			goto bail_unlock;
> -	}
> +	status = vfs_ioc_setflags_check(inode, oldflags, flags);
> +	if (status)
> +		goto bail_unlock;
>  
>  	handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);
>  	if (IS_ERR(handle)) {
> diff --git a/fs/reiserfs/ioctl.c b/fs/reiserfs/ioctl.c
> index acbbaf7a0bb2..92bcb1ecd994 100644
> --- a/fs/reiserfs/ioctl.c
> +++ b/fs/reiserfs/ioctl.c
> @@ -74,13 +74,11 @@ long reiserfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
>  				err = -EPERM;
>  				goto setflags_out;
>  			}
> -			if (((flags ^ REISERFS_I(inode)->
> -			      i_attrs) & (REISERFS_IMMUTABLE_FL |
> -					  REISERFS_APPEND_FL))
> -			    && !capable(CAP_LINUX_IMMUTABLE)) {
> -				err = -EPERM;
> +			err = vfs_ioc_setflags_check(inode,
> +						     REISERFS_I(inode)->i_attrs,
> +						     flags);
> +			if (err)
>  				goto setflags_out;
> -			}
>  			if ((flags & REISERFS_NOTAIL_FL) &&
>  			    S_ISREG(inode->i_mode)) {
>  				int result;
> diff --git a/fs/ubifs/ioctl.c b/fs/ubifs/ioctl.c
> index 4f1a397fda69..bdea836fc38b 100644
> --- a/fs/ubifs/ioctl.c
> +++ b/fs/ubifs/ioctl.c
> @@ -107,18 +107,11 @@ static int setflags(struct inode *inode, int flags)
>  	if (err)
>  		return err;
>  
> -	/*
> -	 * The IMMUTABLE and APPEND_ONLY flags can only be changed by
> -	 * the relevant capability.
> -	 */
>  	mutex_lock(&ui->ui_mutex);
>  	oldflags = ubifs2ioctl(ui->flags);
> -	if ((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL)) {
> -		if (!capable(CAP_LINUX_IMMUTABLE)) {
> -			err = -EPERM;
> -			goto out_unlock;
> -		}
> -	}
> +	err = vfs_ioc_setflags_check(inode, oldflags, flags);
> +	if (err)
> +		goto out_unlock;
>  
>  	ui->flags = ioctl2ubifs(flags);
>  	ubifs_set_inode_flags(inode);
> diff --git a/include/linux/fs.h b/include/linux/fs.h
> index f7fdfe93e25d..1825d055808c 100644
> --- a/include/linux/fs.h
> +++ b/include/linux/fs.h
> @@ -3546,4 +3546,6 @@ static inline struct sock *io_uring_get_socket(struct file *file)
>  }
>  #endif
>  
> +int vfs_ioc_setflags_check(struct inode *inode, int oldflags, int flags);
> +
>  #endif /* _LINUX_FS_H */
> 
-- 
Jan Kara <jack@suse.com>
SUSE Labs, CR



^ permalink raw reply

* [PATCH v5 6/7] i2c: core: Move ACPI gpio IRQ handling into i2c_acpi_get_irq
From: Charles Keepax @ 2019-06-20 13:34 UTC (permalink / raw)
  To: wsa, mika.westerberg
  Cc: jarkko.nikula, andriy.shevchenko, linux-i2c, linux-acpi,
	linux-kernel, benjamin.tissoires, jbroadus, patches
In-Reply-To: <20190620133420.4632-1-ckeepax@opensource.cirrus.com>

It makes sense to contain all the ACPI IRQ handling in a single helper
function.

Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
---

No changes since v4.

Thanks,
Charles

 drivers/i2c/i2c-core-acpi.c | 3 +++
 drivers/i2c/i2c-core-base.c | 3 ---
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/i2c/i2c-core-acpi.c b/drivers/i2c/i2c-core-acpi.c
index f752879772f64..e21e31d661ba7 100644
--- a/drivers/i2c/i2c-core-acpi.c
+++ b/drivers/i2c/i2c-core-acpi.c
@@ -167,6 +167,9 @@ int i2c_acpi_get_irq(struct acpi_device *adev)
 
 	acpi_dev_free_resource_list(&resource_list);
 
+	if (irq == -ENOENT)
+		irq = acpi_dev_gpio_irq_get(adev, 0);
+
 	return irq;
 }
 
diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c
index 060d1a3a7ea4c..95a0380286c1c 100644
--- a/drivers/i2c/i2c-core-base.c
+++ b/drivers/i2c/i2c-core-base.c
@@ -328,9 +328,6 @@ static int i2c_device_probe(struct device *dev)
 				irq = of_irq_get(dev->of_node, 0);
 		} else if (ACPI_COMPANION(dev)) {
 			irq = i2c_acpi_get_irq(ACPI_COMPANION(dev));
-
-			if (irq == -ENOENT)
-				irq = acpi_dev_gpio_irq_get(ACPI_COMPANION(dev), 0);
 		}
 		if (irq == -EPROBE_DEFER)
 			return irq;
-- 
2.11.0

^ permalink raw reply related

* [PATCH v5 5/7] i2c: core: Move ACPI IRQ handling to probe time
From: Charles Keepax @ 2019-06-20 13:34 UTC (permalink / raw)
  To: wsa, mika.westerberg
  Cc: jarkko.nikula, andriy.shevchenko, linux-i2c, linux-acpi,
	linux-kernel, benjamin.tissoires, jbroadus, patches
In-Reply-To: <20190620133420.4632-1-ckeepax@opensource.cirrus.com>

Bring the ACPI path in sync with the device tree path and handle all the
IRQ fetching at probe time. This leaves the only IRQ handling at device
registration time being that which is passed directly through the board
info as either a resource or an actual IRQ number.

Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
---

Changes since v4:
 - Pass acpi_device to i2c_acpi_get_irq
 - Pass the client acpi_device rather than the adaptor, I think (maybe
   hope is more accurate) this should fix the issue seen by Benjamin.

Thanks,
Charles

 drivers/i2c/i2c-core-acpi.c | 5 -----
 drivers/i2c/i2c-core-base.c | 5 ++++-
 2 files changed, 4 insertions(+), 6 deletions(-)

diff --git a/drivers/i2c/i2c-core-acpi.c b/drivers/i2c/i2c-core-acpi.c
index 0ddfcca6091e1..f752879772f64 100644
--- a/drivers/i2c/i2c-core-acpi.c
+++ b/drivers/i2c/i2c-core-acpi.c
@@ -205,11 +205,6 @@ static int i2c_acpi_get_info(struct acpi_device *adev,
 	if (adapter_handle)
 		*adapter_handle = lookup.adapter_handle;
 
-	/* Then fill IRQ number if any */
-	ret = i2c_acpi_get_irq(adev);
-	if (ret > 0)
-		info->irq = ret;
-
 	acpi_set_modalias(adev, dev_name(&adev->dev), info->type,
 			  sizeof(info->type));
 
diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c
index 8a303246d534b..060d1a3a7ea4c 100644
--- a/drivers/i2c/i2c-core-base.c
+++ b/drivers/i2c/i2c-core-base.c
@@ -327,7 +327,10 @@ static int i2c_device_probe(struct device *dev)
 			if (irq == -EINVAL || irq == -ENODATA)
 				irq = of_irq_get(dev->of_node, 0);
 		} else if (ACPI_COMPANION(dev)) {
-			irq = acpi_dev_gpio_irq_get(ACPI_COMPANION(dev), 0);
+			irq = i2c_acpi_get_irq(ACPI_COMPANION(dev));
+
+			if (irq == -ENOENT)
+				irq = acpi_dev_gpio_irq_get(ACPI_COMPANION(dev), 0);
 		}
 		if (irq == -EPROBE_DEFER)
 			return irq;
-- 
2.11.0

^ permalink raw reply related

* [PATCH v5 4/7] i2c: core: Make i2c_acpi_get_irq available to the rest of the I2C core
From: Charles Keepax @ 2019-06-20 13:34 UTC (permalink / raw)
  To: wsa, mika.westerberg
  Cc: jarkko.nikula, andriy.shevchenko, linux-i2c, linux-acpi,
	linux-kernel, benjamin.tissoires, jbroadus, patches
In-Reply-To: <20190620133420.4632-1-ckeepax@opensource.cirrus.com>

In preparation for more refactoring make i2c_acpi_get_irq available
outside i2c-core-acpi.c.

Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
---

Changes since v4:
 - Leave i2c_acpi_get_irq accepting an acpi_device, this should
   avoid the NULL pointer issue we had with i2c_acpi_find_client_by_adev

Thanks,
Charles

 drivers/i2c/i2c-core-acpi.c | 10 +++++++++-
 drivers/i2c/i2c-core.h      |  9 +++++++++
 2 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/drivers/i2c/i2c-core-acpi.c b/drivers/i2c/i2c-core-acpi.c
index 7d4d66ba752d4..0ddfcca6091e1 100644
--- a/drivers/i2c/i2c-core-acpi.c
+++ b/drivers/i2c/i2c-core-acpi.c
@@ -144,7 +144,15 @@ static int i2c_acpi_add_resource(struct acpi_resource *ares, void *data)
 	return 1; /* No need to add resource to the list */
 }
 
-static int i2c_acpi_get_irq(struct acpi_device *adev)
+/**
+ * i2c_acpi_get_irq - get device IRQ number from ACPI
+ * @client: Pointer to the I2C client device
+ *
+ * Find the IRQ number used by a specific client device.
+ *
+ * Return: The IRQ number or an error code.
+ */
+int i2c_acpi_get_irq(struct acpi_device *adev)
 {
 	struct list_head resource_list;
 	int irq = -ENOENT;
diff --git a/drivers/i2c/i2c-core.h b/drivers/i2c/i2c-core.h
index 2a3b28bf826b1..4fbe0a0bcc4c4 100644
--- a/drivers/i2c/i2c-core.h
+++ b/drivers/i2c/i2c-core.h
@@ -58,11 +58,15 @@ static inline int __i2c_check_suspended(struct i2c_adapter *adap)
 	return 0;
 }
 
+struct acpi_device;
+
 #ifdef CONFIG_ACPI
 const struct acpi_device_id *
 i2c_acpi_match_device(const struct acpi_device_id *matches,
 		      struct i2c_client *client);
 void i2c_acpi_register_devices(struct i2c_adapter *adap);
+
+int i2c_acpi_get_irq(struct acpi_device *adev);
 #else /* CONFIG_ACPI */
 static inline void i2c_acpi_register_devices(struct i2c_adapter *adap) { }
 static inline const struct acpi_device_id *
@@ -71,6 +75,11 @@ i2c_acpi_match_device(const struct acpi_device_id *matches,
 {
 	return NULL;
 }
+
+static inline int i2c_acpi_get_irq(struct acpi_device *adev)
+{
+	return 0;
+}
 #endif /* CONFIG_ACPI */
 extern struct notifier_block i2c_acpi_notifier;
 
-- 
2.11.0

^ permalink raw reply related

* [PATCH v5 3/7] i2c: acpi: Factor out getting the IRQ from ACPI
From: Charles Keepax @ 2019-06-20 13:34 UTC (permalink / raw)
  To: wsa, mika.westerberg
  Cc: jarkko.nikula, andriy.shevchenko, linux-i2c, linux-acpi,
	linux-kernel, benjamin.tissoires, jbroadus, patches
In-Reply-To: <20190620133420.4632-1-ckeepax@opensource.cirrus.com>

In preparation for future refactoring factor out the fetch of the IRQ
into its own helper function.

Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
---

No changes since v4.

Thanks,
Charles

 drivers/i2c/i2c-core-acpi.c | 33 +++++++++++++++++++++------------
 1 file changed, 21 insertions(+), 12 deletions(-)

diff --git a/drivers/i2c/i2c-core-acpi.c b/drivers/i2c/i2c-core-acpi.c
index 47d5b1c5ec9e0..7d4d66ba752d4 100644
--- a/drivers/i2c/i2c-core-acpi.c
+++ b/drivers/i2c/i2c-core-acpi.c
@@ -144,14 +144,30 @@ static int i2c_acpi_add_resource(struct acpi_resource *ares, void *data)
 	return 1; /* No need to add resource to the list */
 }
 
+static int i2c_acpi_get_irq(struct acpi_device *adev)
+{
+	struct list_head resource_list;
+	int irq = -ENOENT;
+	int ret;
+
+	INIT_LIST_HEAD(&resource_list);
+
+	ret = acpi_dev_get_resources(adev, &resource_list,
+				     i2c_acpi_add_resource, &irq);
+	if (ret < 0)
+		return -EINVAL;
+
+	acpi_dev_free_resource_list(&resource_list);
+
+	return irq;
+}
+
 static int i2c_acpi_get_info(struct acpi_device *adev,
 			     struct i2c_board_info *info,
 			     struct i2c_adapter *adapter,
 			     acpi_handle *adapter_handle)
 {
-	struct list_head resource_list;
 	struct i2c_acpi_lookup lookup;
-	int irq = -ENOENT;
 	int ret;
 
 	memset(&lookup, 0, sizeof(lookup));
@@ -182,16 +198,9 @@ static int i2c_acpi_get_info(struct acpi_device *adev,
 		*adapter_handle = lookup.adapter_handle;
 
 	/* Then fill IRQ number if any */
-	INIT_LIST_HEAD(&resource_list);
-	ret = acpi_dev_get_resources(adev, &resource_list,
-				     i2c_acpi_add_resource, &irq);
-	if (ret < 0)
-		return -EINVAL;
-
-	if (irq > 0)
-		info->irq = irq;
-
-	acpi_dev_free_resource_list(&resource_list);
+	ret = i2c_acpi_get_irq(adev);
+	if (ret > 0)
+		info->irq = ret;
 
 	acpi_set_modalias(adev, dev_name(&adev->dev), info->type,
 			  sizeof(info->type));
-- 
2.11.0

^ permalink raw reply related

* [PATCH v5 2/7] i2c: acpi: Use available IRQ helper functions
From: Charles Keepax @ 2019-06-20 13:34 UTC (permalink / raw)
  To: wsa, mika.westerberg
  Cc: jarkko.nikula, andriy.shevchenko, linux-i2c, linux-acpi,
	linux-kernel, benjamin.tissoires, jbroadus, patches
In-Reply-To: <20190620133420.4632-1-ckeepax@opensource.cirrus.com>

Use the available IRQ helper functions, most of the functions have
additional helpful side affects like configuring the trigger type of the
IRQ.

Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
---

No changes since v4.

Thanks,
Charles

 drivers/i2c/i2c-core-acpi.c | 24 ++++++++++++++++--------
 1 file changed, 16 insertions(+), 8 deletions(-)

diff --git a/drivers/i2c/i2c-core-acpi.c b/drivers/i2c/i2c-core-acpi.c
index f1d648962b223..47d5b1c5ec9e0 100644
--- a/drivers/i2c/i2c-core-acpi.c
+++ b/drivers/i2c/i2c-core-acpi.c
@@ -133,14 +133,25 @@ static int i2c_acpi_do_lookup(struct acpi_device *adev,
 	return 0;
 }
 
+static int i2c_acpi_add_resource(struct acpi_resource *ares, void *data)
+{
+	int *irq = data;
+	struct resource r;
+
+	if (*irq <= 0 && acpi_dev_resource_interrupt(ares, 0, &r))
+		*irq = i2c_dev_irq_from_resources(&r, 1);
+
+	return 1; /* No need to add resource to the list */
+}
+
 static int i2c_acpi_get_info(struct acpi_device *adev,
 			     struct i2c_board_info *info,
 			     struct i2c_adapter *adapter,
 			     acpi_handle *adapter_handle)
 {
 	struct list_head resource_list;
-	struct resource_entry *entry;
 	struct i2c_acpi_lookup lookup;
+	int irq = -ENOENT;
 	int ret;
 
 	memset(&lookup, 0, sizeof(lookup));
@@ -172,16 +183,13 @@ static int i2c_acpi_get_info(struct acpi_device *adev,
 
 	/* Then fill IRQ number if any */
 	INIT_LIST_HEAD(&resource_list);
-	ret = acpi_dev_get_resources(adev, &resource_list, NULL, NULL);
+	ret = acpi_dev_get_resources(adev, &resource_list,
+				     i2c_acpi_add_resource, &irq);
 	if (ret < 0)
 		return -EINVAL;
 
-	resource_list_for_each_entry(entry, &resource_list) {
-		if (resource_type(entry->res) == IORESOURCE_IRQ) {
-			info->irq = entry->res->start;
-			break;
-		}
-	}
+	if (irq > 0)
+		info->irq = irq;
 
 	acpi_dev_free_resource_list(&resource_list);
 
-- 
2.11.0

^ permalink raw reply related

* [PATCH v5 1/7] i2c: core: Allow whole core to use i2c_dev_irq_from_resources
From: Charles Keepax @ 2019-06-20 13:34 UTC (permalink / raw)
  To: wsa, mika.westerberg
  Cc: jarkko.nikula, andriy.shevchenko, linux-i2c, linux-acpi,
	linux-kernel, benjamin.tissoires, jbroadus, patches
In-Reply-To: <20190620133420.4632-1-ckeepax@opensource.cirrus.com>

Remove the static from i2c_dev_irq_from _resources so that other parts
of the core code can use this helper function.

Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
---

No changes since v4.

Thanks,
Charles

 drivers/i2c/i2c-core-base.c | 4 ++--
 drivers/i2c/i2c-core.h      | 2 ++
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c
index 2569e97f9bf35..8a303246d534b 100644
--- a/drivers/i2c/i2c-core-base.c
+++ b/drivers/i2c/i2c-core-base.c
@@ -679,8 +679,8 @@ static void i2c_dev_set_name(struct i2c_adapter *adap,
 		     i2c_encode_flags_to_addr(client));
 }
 
-static int i2c_dev_irq_from_resources(const struct resource *resources,
-				      unsigned int num_resources)
+int i2c_dev_irq_from_resources(const struct resource *resources,
+			       unsigned int num_resources)
 {
 	struct irq_data *irqd;
 	int i;
diff --git a/drivers/i2c/i2c-core.h b/drivers/i2c/i2c-core.h
index 851c11b4c0f3a..2a3b28bf826b1 100644
--- a/drivers/i2c/i2c-core.h
+++ b/drivers/i2c/i2c-core.h
@@ -19,6 +19,8 @@ extern struct list_head	__i2c_board_list;
 extern int		__i2c_first_dynamic_bus_num;
 
 int i2c_check_7bit_addr_validity_strict(unsigned short addr);
+int i2c_dev_irq_from_resources(const struct resource *resources,
+			       unsigned int num_resources);
 
 /*
  * We only allow atomic transfers for very late communication, e.g. to send
-- 
2.11.0

^ permalink raw reply related

* [PATCH v5 0/7] I2C IRQ Probe Improvements
From: Charles Keepax @ 2019-06-20 13:34 UTC (permalink / raw)
  To: wsa, mika.westerberg
  Cc: jarkko.nikula, andriy.shevchenko, linux-i2c, linux-acpi,
	linux-kernel, benjamin.tissoires, jbroadus, patches

This series attempts to align as much IRQ handling into the
probe path as possible. Note that I don't have a great setup
for testing these patches so they are mostly just build tested
and need careful review and testing before any of them are
merged.

The series brings the ACPI path inline with the way the device
tree path handles the IRQ entirely at probe time. However,
it still leaves any IRQ specified through the board_info as
being handled at device time. In that case we need to cache
something from the board_info until probe time, which leaves
any alternative solution with something basically the same as
the current handling although perhaps caching more stuff.

Thanks,
Charles

See previous discussions:
 - https://lkml.org/lkml/2019/2/15/989
 - https://www.spinics.net/lists/linux-i2c/msg39541.html

Charles Keepax (7):
  i2c: core: Allow whole core to use i2c_dev_irq_from_resources
  i2c: acpi: Use available IRQ helper functions
  i2c: acpi: Factor out getting the IRQ from ACPI
  i2c: core: Make i2c_acpi_get_irq available to the rest of the I2C core
  i2c: core: Move ACPI IRQ handling to probe time
  i2c: core: Move ACPI gpio IRQ handling into i2c_acpi_get_irq
  i2c: core: Tidy up handling of init_irq

 drivers/i2c/i2c-core-acpi.c | 57 +++++++++++++++++++++++++++++++--------------
 drivers/i2c/i2c-core-base.c | 11 +++++----
 drivers/i2c/i2c-core.h      | 11 +++++++++
 3 files changed, 57 insertions(+), 22 deletions(-)

-- 
2.11.0

^ permalink raw reply

* Re: [dpdk-dev] [PATCH v3 2/3] net/ice: add generic flow API
From: Aaron Conole @ 2019-06-20 13:33 UTC (permalink / raw)
  To: Qiming Yang; +Cc: dev
In-Reply-To: <20190620053449.32959-3-qiming.yang@intel.com>

Qiming Yang <qiming.yang@intel.com> writes:

> This patch adds ice_flow_create, ice_flow_destroy,
> ice_flow_flush and ice_flow_validate support,
> these are used to handle all the generic filters.
>
> Signed-off-by: Qiming Yang <qiming.yang@intel.com>
> ---
>  drivers/net/ice/Makefile           |   1 +
>  drivers/net/ice/ice_ethdev.c       |  44 +++
>  drivers/net/ice/ice_ethdev.h       |   5 +
>  drivers/net/ice/ice_generic_flow.c | 682 +++++++++++++++++++++++++++++++++++++
>  drivers/net/ice/ice_generic_flow.h | 654 +++++++++++++++++++++++++++++++++++
>  drivers/net/ice/meson.build        |   1 +
>  6 files changed, 1387 insertions(+)
>  create mode 100644 drivers/net/ice/ice_generic_flow.c
>  create mode 100644 drivers/net/ice/ice_generic_flow.h
>
> diff --git a/drivers/net/ice/Makefile b/drivers/net/ice/Makefile
> index b10d826..32abeb6 100644
> --- a/drivers/net/ice/Makefile
> +++ b/drivers/net/ice/Makefile
> @@ -79,5 +79,6 @@ endif
>  ifeq ($(CC_AVX2_SUPPORT), 1)
>  	SRCS-$(CONFIG_RTE_LIBRTE_ICE_PMD) += ice_rxtx_vec_avx2.c
>  endif
> +SRCS-$(CONFIG_RTE_LIBRTE_ICE_PMD) += ice_generic_flow.c
>  
>  include $(RTE_SDK)/mk/rte.lib.mk
> diff --git a/drivers/net/ice/ice_ethdev.c b/drivers/net/ice/ice_ethdev.c
> index a94aa7e..8ee06d1 100644
> --- a/drivers/net/ice/ice_ethdev.c
> +++ b/drivers/net/ice/ice_ethdev.c
> @@ -15,6 +15,7 @@
>  #include "base/ice_dcb.h"
>  #include "ice_ethdev.h"
>  #include "ice_rxtx.h"
> +#include "ice_switch_filter.h"
>  
>  #define ICE_MAX_QP_NUM "max_queue_pair_num"
>  #define ICE_DFLT_OUTER_TAG_TYPE ICE_AQ_VSI_OUTER_TAG_VLAN_9100
> @@ -83,6 +84,10 @@ static int ice_xstats_get(struct rte_eth_dev *dev,
>  static int ice_xstats_get_names(struct rte_eth_dev *dev,
>  				struct rte_eth_xstat_name *xstats_names,
>  				unsigned int limit);
> +static int ice_dev_filter_ctrl(struct rte_eth_dev *dev,
> +			enum rte_filter_type filter_type,
> +			enum rte_filter_op filter_op,
> +			void *arg);
>  
>  static const struct rte_pci_id pci_id_ice_map[] = {
>  	{ RTE_PCI_DEVICE(ICE_INTEL_VENDOR_ID, ICE_DEV_ID_E810C_BACKPLANE) },
> @@ -141,6 +146,7 @@ static const struct eth_dev_ops ice_eth_dev_ops = {
>  	.xstats_get                   = ice_xstats_get,
>  	.xstats_get_names             = ice_xstats_get_names,
>  	.xstats_reset                 = ice_stats_reset,
> +	.filter_ctrl                  = ice_dev_filter_ctrl,
>  };
>  
>  /* store statistics names and its offset in stats structure */
> @@ -1478,6 +1484,8 @@ ice_dev_init(struct rte_eth_dev *dev)
>  	/* get base queue pairs index  in the device */
>  	ice_base_queue_get(pf);
>  
> +	TAILQ_INIT(&pf->flow_list);
> +
>  	return 0;
>  
>  err_pf_setup:
> @@ -1620,6 +1628,8 @@ ice_dev_uninit(struct rte_eth_dev *dev)
>  {
>  	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
>  	struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
> +	struct ice_pf *pf = ICE_DEV_PRIVATE_TO_PF(dev->data->dev_private);
> +	struct rte_flow *p_flow;
>  
>  	ice_dev_close(dev);
>  
> @@ -1637,6 +1647,13 @@ ice_dev_uninit(struct rte_eth_dev *dev)
>  	rte_intr_callback_unregister(intr_handle,
>  				     ice_interrupt_handler, dev);
>  
> +	/* Remove all flows */
> +	while ((p_flow = TAILQ_FIRST(&pf->flow_list))) {
> +		TAILQ_REMOVE(&pf->flow_list, p_flow, node);
> +		ice_free_switch_filter_rule(p_flow->rule);
> +		rte_free(p_flow);
> +	}
> +
>  	return 0;
>  }
>  
> @@ -3622,6 +3639,33 @@ static int ice_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
>  }
>  
>  static int
> +ice_dev_filter_ctrl(struct rte_eth_dev *dev,
> +		     enum rte_filter_type filter_type,
> +		     enum rte_filter_op filter_op,
> +		     void *arg)
> +{
> +	int ret = 0;
> +
> +	if (!dev)
> +		return -EINVAL;
> +
> +	switch (filter_type) {
> +	case RTE_ETH_FILTER_GENERIC:
> +		if (filter_op != RTE_ETH_FILTER_GET)
> +			return -EINVAL;
> +		*(const void **)arg = &ice_flow_ops;
> +		break;
> +	default:
> +		PMD_DRV_LOG(WARNING, "Filter type (%d) not supported",
> +					filter_type);
> +		ret = -EINVAL;
> +		break;
> +	}
> +
> +	return ret;
> +}
> +
> +static int
>  ice_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
>  	      struct rte_pci_device *pci_dev)
>  {
> diff --git a/drivers/net/ice/ice_ethdev.h b/drivers/net/ice/ice_ethdev.h
> index 50b966c..8a52239 100644
> --- a/drivers/net/ice/ice_ethdev.h
> +++ b/drivers/net/ice/ice_ethdev.h
> @@ -234,12 +234,16 @@ struct ice_vsi {
>  	bool offset_loaded;
>  };
>  
> +extern const struct rte_flow_ops ice_flow_ops;
> +
>  /* Struct to store flow created. */
>  struct rte_flow {
>  	TAILQ_ENTRY(rte_flow) node;
>  	void *rule;
>  };
>  
> +TAILQ_HEAD(ice_flow_list, rte_flow);
> +
>  struct ice_pf {
>  	struct ice_adapter *adapter; /* The adapter this PF associate to */
>  	struct ice_vsi *main_vsi; /* pointer to main VSI structure */
> @@ -266,6 +270,7 @@ struct ice_pf {
>  	struct ice_eth_stats internal_stats;
>  	bool offset_loaded;
>  	bool adapter_stopped;
> +	struct ice_flow_list flow_list;
>  };
>  
>  /**
> diff --git a/drivers/net/ice/ice_generic_flow.c b/drivers/net/ice/ice_generic_flow.c
> new file mode 100644
> index 0000000..c6fce88
> --- /dev/null
> +++ b/drivers/net/ice/ice_generic_flow.c
> @@ -0,0 +1,682 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(c) 2019 Intel Corporation
> + */
> +
> +#include <sys/queue.h>
> +#include <stdio.h>
> +#include <errno.h>
> +#include <stdint.h>
> +#include <string.h>
> +#include <unistd.h>
> +#include <stdarg.h>
> +
> +#include <rte_ether.h>
> +#include <rte_ethdev_driver.h>
> +#include <rte_malloc.h>
> +
> +#include "ice_ethdev.h"
> +#include "ice_generic_flow.h"
> +#include "ice_switch_filter.h"
> +
> +static int ice_flow_validate(struct rte_eth_dev *dev,
> +		const struct rte_flow_attr *attr,
> +		const struct rte_flow_item pattern[],
> +		const struct rte_flow_action actions[],
> +		struct rte_flow_error *error);
> +static struct rte_flow *ice_flow_create(struct rte_eth_dev *dev,
> +		const struct rte_flow_attr *attr,
> +		const struct rte_flow_item pattern[],
> +		const struct rte_flow_action actions[],
> +		struct rte_flow_error *error);
> +static int ice_flow_destroy(struct rte_eth_dev *dev,
> +		struct rte_flow *flow,
> +		struct rte_flow_error *error);
> +static int ice_flow_flush(struct rte_eth_dev *dev,
> +		struct rte_flow_error *error);
> +
> +const struct rte_flow_ops ice_flow_ops = {
> +	.validate = ice_flow_validate,
> +	.create = ice_flow_create,
> +	.destroy = ice_flow_destroy,
> +	.flush = ice_flow_flush,
> +};
> +
> +static int
> +ice_flow_valid_attr(const struct rte_flow_attr *attr,
> +		     struct rte_flow_error *error)
> +{
> +	/* Must be input direction */
> +	if (!attr->ingress) {
> +		rte_flow_error_set(error, EINVAL,
> +				   RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
> +				   attr, "Only support ingress.");
> +		return -rte_errno;
> +	}
> +
> +	/* Not supported */
> +	if (attr->egress) {
> +		rte_flow_error_set(error, EINVAL,
> +				   RTE_FLOW_ERROR_TYPE_ATTR_EGRESS,
> +				   attr, "Not support egress.");
> +		return -rte_errno;
> +	}
> +
> +	/* Not supported */
> +	if (attr->priority) {
> +		rte_flow_error_set(error, EINVAL,
> +				   RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY,
> +				   attr, "Not support priority.");
> +		return -rte_errno;
> +	}
> +
> +	/* Not supported */
> +	if (attr->group) {
> +		rte_flow_error_set(error, EINVAL,
> +				   RTE_FLOW_ERROR_TYPE_ATTR_GROUP,
> +				   attr, "Not support group.");
> +		return -rte_errno;
> +	}
> +
> +	return 0;
> +}
> +
> +/* Find the first VOID or non-VOID item pointer */
> +static const struct rte_flow_item *
> +ice_find_first_item(const struct rte_flow_item *item, bool is_void)
> +{
> +	bool is_find;
> +
> +	while (item->type != RTE_FLOW_ITEM_TYPE_END) {
> +		if (is_void)
> +			is_find = item->type == RTE_FLOW_ITEM_TYPE_VOID;
> +		else
> +			is_find = item->type != RTE_FLOW_ITEM_TYPE_VOID;
> +		if (is_find)
> +			break;
> +		item++;
> +	}
> +	return item;
> +}
> +
> +/* Skip all VOID items of the pattern */
> +static void
> +ice_pattern_skip_void_item(struct rte_flow_item *items,
> +			    const struct rte_flow_item *pattern)
> +{
> +	uint32_t cpy_count = 0;
> +	const struct rte_flow_item *pb = pattern, *pe = pattern;
> +
> +	for (;;) {
> +		/* Find a non-void item first */
> +		pb = ice_find_first_item(pb, false);
> +		if (pb->type == RTE_FLOW_ITEM_TYPE_END) {
> +			pe = pb;
> +			break;
> +		}
> +
> +		/* Find a void item */
> +		pe = ice_find_first_item(pb + 1, true);
> +
> +		cpy_count = pe - pb;
> +		rte_memcpy(items, pb, sizeof(struct rte_flow_item) * cpy_count);
> +
> +		items += cpy_count;
> +
> +		if (pe->type == RTE_FLOW_ITEM_TYPE_END) {
> +			pb = pe;
> +			break;
> +		}
> +
> +		pb = pe + 1;
> +	}
> +	/* Copy the END item. */
> +	rte_memcpy(items, pe, sizeof(struct rte_flow_item));
> +}
> +
> +/* Check if the pattern matches a supported item type array */
> +static bool
> +ice_match_pattern(enum rte_flow_item_type *item_array,
> +		const struct rte_flow_item *pattern)
> +{
> +	const struct rte_flow_item *item = pattern;
> +
> +	while ((*item_array == item->type) &&
> +	       (*item_array != RTE_FLOW_ITEM_TYPE_END)) {
> +		item_array++;
> +		item++;
> +	}
> +
> +	return (*item_array == RTE_FLOW_ITEM_TYPE_END &&
> +		item->type == RTE_FLOW_ITEM_TYPE_END);
> +}
> +
> +static uint64_t ice_flow_valid_pattern(const struct rte_flow_item pattern[],
> +		struct rte_flow_error *error)
> +{
> +	uint16_t i = 0;
> +	uint64_t inset;
> +	struct rte_flow_item *items; /* used for pattern without VOID items */
> +	uint32_t item_num = 0; /* non-void item number */
> +
> +	/* Get the non-void item number of pattern */
> +	while ((pattern + i)->type != RTE_FLOW_ITEM_TYPE_END) {
> +		if ((pattern + i)->type != RTE_FLOW_ITEM_TYPE_VOID)
> +			item_num++;
> +		i++;
> +	}
> +	item_num++;
> +
> +	items = rte_zmalloc("ice_pattern",
> +			    item_num * sizeof(struct rte_flow_item), 0);
> +	if (!items) {
> +		rte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_ITEM_NUM,
> +				   NULL, "No memory for PMD internal items.");
> +		return -ENOMEM;
> +	}
> +
> +	ice_pattern_skip_void_item(items, pattern);
> +
> +	for (i = 0; i < RTE_DIM(ice_supported_patterns); i++)
> +		if (ice_match_pattern(ice_supported_patterns[i].items,
> +				      items)) {
> +			inset = ice_supported_patterns[i].sw_fields;
> +			rte_free(items);
> +			return inset;
> +		}
> +	rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
> +			   pattern, "Unsupported pattern");
> +
> +	rte_free(items);
> +	return 0;
> +}
> +
> +static uint64_t ice_get_flow_field(const struct rte_flow_item pattern[],
> +			struct rte_flow_error *error)
> +{
> +	const struct rte_flow_item *item = pattern;
> +	const struct rte_flow_item_eth *eth_spec, *eth_mask;
> +	const struct rte_flow_item_ipv4 *ipv4_spec, *ipv4_mask;
> +	const struct rte_flow_item_ipv6 *ipv6_spec, *ipv6_mask;
> +	const struct rte_flow_item_tcp *tcp_spec, *tcp_mask;
> +	const struct rte_flow_item_udp *udp_spec, *udp_mask;
> +	const struct rte_flow_item_sctp *sctp_spec, *sctp_mask;
> +	const struct rte_flow_item_icmp *icmp_mask;
> +	const struct rte_flow_item_icmp6 *icmp6_mask;
> +	const struct rte_flow_item_vxlan *vxlan_spec, *vxlan_mask;
> +	const struct rte_flow_item_nvgre *nvgre_spec, *nvgre_mask;
> +	enum rte_flow_item_type item_type;
> +	uint8_t  ipv6_addr_mask[16] = {
> +		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> +		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
> +	uint64_t input_set = ICE_INSET_NONE;
> +	bool outer_ip = true;
> +	bool outer_l4 = true;
> +
> +	for (; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
> +		if (item->last) {
> +			rte_flow_error_set(error, EINVAL,
> +					   RTE_FLOW_ERROR_TYPE_ITEM,
> +					   item,
> +					   "Not support range");
> +			return 0;
> +		}
> +		item_type = item->type;
> +		switch (item_type) {
> +		case RTE_FLOW_ITEM_TYPE_ETH:
> +			eth_spec = item->spec;
> +			eth_mask = item->mask;
> +
> +			if (eth_spec && eth_mask) {
> +				if (rte_is_broadcast_ether_addr(&eth_mask->src))
> +					input_set |= ICE_INSET_SMAC;
> +				if (rte_is_broadcast_ether_addr(&eth_mask->dst))
> +					input_set |= ICE_INSET_DMAC;
> +				if (eth_mask->type == RTE_BE16(0xffff))
> +					input_set |= ICE_INSET_ETHERTYPE;
> +			}
> +			break;
> +		case RTE_FLOW_ITEM_TYPE_IPV4:
> +			ipv4_spec = item->spec;
> +			ipv4_mask = item->mask;
> +
> +			if (!(ipv4_spec && ipv4_mask)) {
> +				rte_flow_error_set(error, EINVAL,
> +					   RTE_FLOW_ERROR_TYPE_ITEM,
> +					   item,
> +					   "Invalid IPv4 spec or mask.");
> +				return 0;
> +			}
> +
> +			/* Check IPv4 mask and update input set */
> +			if (ipv4_mask->hdr.version_ihl ||
> +			    ipv4_mask->hdr.total_length ||
> +			    ipv4_mask->hdr.packet_id ||
> +			    ipv4_mask->hdr.hdr_checksum) {
> +				rte_flow_error_set(error, EINVAL,
> +					   RTE_FLOW_ERROR_TYPE_ITEM,
> +					   item,
> +					   "Invalid IPv4 mask.");
> +				return 0;
> +			}
> +
> +			if (outer_ip) {
> +				if (ipv4_mask->hdr.src_addr == UINT32_MAX)
> +					input_set |= ICE_INSET_IPV4_SRC;
> +				if (ipv4_mask->hdr.dst_addr == UINT32_MAX)
> +					input_set |= ICE_INSET_IPV4_DST;
> +				if (ipv4_mask->hdr.type_of_service == UINT8_MAX)
> +					input_set |= ICE_INSET_IPV4_TOS;
> +				if (ipv4_mask->hdr.time_to_live == UINT8_MAX)
> +					input_set |= ICE_INSET_IPV4_TTL;
> +				if (ipv4_mask->hdr.fragment_offset == 0)
> +					input_set |= ICE_INSET_IPV4_PROTO;
> +				outer_ip = false;
> +			} else {
> +				if (ipv4_mask->hdr.src_addr == UINT32_MAX)
> +					input_set |= ICE_INSET_TUN_IPV4_SRC;
> +				if (ipv4_mask->hdr.dst_addr == UINT32_MAX)
> +					input_set |= ICE_INSET_TUN_IPV4_DST;
> +				if (ipv4_mask->hdr.time_to_live == UINT8_MAX)
> +					input_set |= ICE_INSET_TUN_IPV4_TTL;
> +				if (ipv4_mask->hdr.next_proto_id == UINT8_MAX)
> +					input_set |= ICE_INSET_TUN_IPV4_PROTO;
> +			}
> +			break;
> +		case RTE_FLOW_ITEM_TYPE_IPV6:
> +			ipv6_spec = item->spec;
> +			ipv6_mask = item->mask;
> +
> +			if (!(ipv6_spec && ipv6_mask)) {
> +				rte_flow_error_set(error, EINVAL,
> +					RTE_FLOW_ERROR_TYPE_ITEM,
> +					item, "Invalid IPv6 spec or mask");
> +				return 0;
> +			}
> +
> +			if (ipv6_mask->hdr.payload_len ||
> +			    ipv6_mask->hdr.vtc_flow) {
> +				rte_flow_error_set(error, EINVAL,
> +					   RTE_FLOW_ERROR_TYPE_ITEM,
> +					   item,
> +					   "Invalid IPv6 mask");
> +				return 0;
> +			}
> +
> +			if (outer_ip) {
> +				if (!memcmp(ipv6_mask->hdr.src_addr,
> +					    ipv6_addr_mask,
> +					    RTE_DIM(ipv6_mask->hdr.src_addr)))
> +					input_set |= ICE_INSET_IPV6_SRC;
> +				if (!memcmp(ipv6_mask->hdr.dst_addr,
> +					    ipv6_addr_mask,
> +					    RTE_DIM(ipv6_mask->hdr.dst_addr)))
> +					input_set |= ICE_INSET_IPV6_DST;
> +				if (ipv6_mask->hdr.proto == UINT8_MAX)
> +					input_set |= ICE_INSET_IPV6_NEXT_HDR;
> +				if (ipv6_mask->hdr.hop_limits == UINT8_MAX)
> +					input_set |= ICE_INSET_IPV6_HOP_LIMIT;
> +				outer_ip = false;
> +			} else {
> +				if (!memcmp(ipv6_mask->hdr.src_addr,
> +					    ipv6_addr_mask,
> +					    RTE_DIM(ipv6_mask->hdr.src_addr)))
> +					input_set |= ICE_INSET_TUN_IPV6_SRC;
> +				if (!memcmp(ipv6_mask->hdr.dst_addr,
> +					    ipv6_addr_mask,
> +					    RTE_DIM(ipv6_mask->hdr.dst_addr)))
> +					input_set |= ICE_INSET_TUN_IPV6_DST;
> +				if (ipv6_mask->hdr.proto == UINT8_MAX)
> +					input_set |= ICE_INSET_TUN_IPV6_PROTO;
> +				if (ipv6_mask->hdr.hop_limits == UINT8_MAX)
> +					input_set |= ICE_INSET_TUN_IPV6_TTL;
> +			}
> +
> +			break;
> +		case RTE_FLOW_ITEM_TYPE_UDP:
> +			udp_spec = item->spec;
> +			udp_mask = item->mask;
> +
> +			if (!(udp_spec && udp_mask)) {
> +				rte_flow_error_set(error, EINVAL,
> +						   RTE_FLOW_ERROR_TYPE_ITEM,
> +						   item, "Invalid UDP mask");
> +				return 0;
> +			}
> +
> +			/* Check UDP mask and update input set*/
> +			if (udp_mask->hdr.dgram_len ||
> +			    udp_mask->hdr.dgram_cksum) {
> +				rte_flow_error_set(error, EINVAL,
> +						   RTE_FLOW_ERROR_TYPE_ITEM,
> +						   item,
> +						   "Invalid UDP mask");
> +				return 0;
> +			}
> +
> +			if (outer_l4) {
> +				if (udp_mask->hdr.src_port == UINT16_MAX)
> +					input_set |= ICE_INSET_SRC_PORT;
> +				if (udp_mask->hdr.dst_port == UINT16_MAX)
> +					input_set |= ICE_INSET_DST_PORT;
> +				outer_l4 = false;
> +			} else {
> +				if (udp_mask->hdr.src_port == UINT16_MAX)
> +					input_set |= ICE_INSET_TUN_SRC_PORT;
> +				if (udp_mask->hdr.dst_port == UINT16_MAX)
> +					input_set |= ICE_INSET_TUN_DST_PORT;
> +			}
> +
> +			break;
> +		case RTE_FLOW_ITEM_TYPE_TCP:
> +			tcp_spec = item->spec;
> +			tcp_mask = item->mask;
> +
> +			if (!(tcp_spec && tcp_mask)) {
> +				rte_flow_error_set(error, EINVAL,
> +						   RTE_FLOW_ERROR_TYPE_ITEM,
> +						   item, "Invalid TCP mask");
> +				return 0;
> +			}
> +
> +			/* Check TCP mask and update input set */
> +			if (tcp_mask->hdr.sent_seq ||
> +			    tcp_mask->hdr.recv_ack ||
> +			    tcp_mask->hdr.data_off ||
> +			    tcp_mask->hdr.tcp_flags ||
> +			    tcp_mask->hdr.rx_win ||
> +			    tcp_mask->hdr.cksum ||
> +			    tcp_mask->hdr.tcp_urp) {
> +				rte_flow_error_set(error, EINVAL,
> +						   RTE_FLOW_ERROR_TYPE_ITEM,
> +						   item,
> +						   "Invalid TCP mask");
> +				return 0;
> +			}
> +
> +			if (outer_l4) {
> +				if (tcp_mask->hdr.src_port == UINT16_MAX)
> +					input_set |= ICE_INSET_SRC_PORT;
> +				if (tcp_mask->hdr.dst_port == UINT16_MAX)
> +					input_set |= ICE_INSET_DST_PORT;
> +				outer_l4 = false;
> +			} else {
> +				if (tcp_mask->hdr.src_port == UINT16_MAX)
> +					input_set |= ICE_INSET_TUN_SRC_PORT;
> +				if (tcp_mask->hdr.dst_port == UINT16_MAX)
> +					input_set |= ICE_INSET_TUN_DST_PORT;
> +			}
> +
> +			break;
> +		case RTE_FLOW_ITEM_TYPE_SCTP:
> +			sctp_spec = item->spec;
> +			sctp_mask = item->mask;
> +
> +			if (!(sctp_spec && sctp_mask)) {
> +				rte_flow_error_set(error, EINVAL,
> +						   RTE_FLOW_ERROR_TYPE_ITEM,
> +						   item, "Invalid SCTP mask");
> +				return 0;
> +			}
> +
> +			/* Check SCTP mask and update input set */
> +			if (sctp_mask->hdr.cksum) {
> +				rte_flow_error_set(error, EINVAL,
> +					   RTE_FLOW_ERROR_TYPE_ITEM,
> +					   item,
> +					   "Invalid SCTP mask");
> +				return 0;
> +			}
> +
> +			if (outer_l4) {
> +				if (sctp_mask->hdr.src_port == UINT16_MAX)
> +					input_set |= ICE_INSET_SRC_PORT;
> +				if (sctp_mask->hdr.dst_port == UINT16_MAX)
> +					input_set |= ICE_INSET_DST_PORT;
> +				outer_l4 = false;
> +			} else {
> +				if (sctp_mask->hdr.src_port == UINT16_MAX)
> +					input_set |= ICE_INSET_TUN_SRC_PORT;
> +				if (sctp_mask->hdr.dst_port == UINT16_MAX)
> +					input_set |= ICE_INSET_TUN_DST_PORT;
> +			}
> +
> +			break;
> +		case RTE_FLOW_ITEM_TYPE_ICMP:
> +			icmp_mask = item->mask;
> +			if (icmp_mask->hdr.icmp_code ||
> +			    icmp_mask->hdr.icmp_cksum ||
> +			    icmp_mask->hdr.icmp_ident ||
> +			    icmp_mask->hdr.icmp_seq_nb) {
> +				rte_flow_error_set(error, EINVAL,
> +						   RTE_FLOW_ERROR_TYPE_ITEM,
> +						   item,
> +						   "Invalid ICMP mask");
> +				return 0;
> +			}
> +
> +			if (icmp_mask->hdr.icmp_type == UINT8_MAX)
> +				input_set |= ICE_INSET_ICMP;
> +			break;
> +		case RTE_FLOW_ITEM_TYPE_ICMP6:
> +			icmp6_mask = item->mask;
> +			if (icmp6_mask->code ||
> +			    icmp6_mask->checksum) {
> +				rte_flow_error_set(error, EINVAL,
> +						   RTE_FLOW_ERROR_TYPE_ITEM,
> +						   item,
> +						   "Invalid ICMP6 mask");
> +				return 0;
> +			}
> +
> +			if (icmp6_mask->type == UINT8_MAX)
> +			input_set |= ICE_INSET_ICMP6;
> +			break;
> +		case RTE_FLOW_ITEM_TYPE_VXLAN:
> +			vxlan_spec = item->spec;
> +			vxlan_mask = item->mask;
> +			/* Check if VXLAN item is used to describe protocol.
> +			 * If yes, both spec and mask should be NULL.
> +			 * If no, both spec and mask shouldn't be NULL.
> +			 */
> +			if ((!vxlan_spec && vxlan_mask) ||
> +			    (vxlan_spec && !vxlan_mask)) {
> +				rte_flow_error_set(error, EINVAL,
> +					   RTE_FLOW_ERROR_TYPE_ITEM,
> +					   item,
> +					   "Invalid VXLAN item");
> +				return -rte_errno;
> +			}
> +
> +			break;
> +		case RTE_FLOW_ITEM_TYPE_NVGRE:
> +			nvgre_spec = item->spec;
> +			nvgre_mask = item->mask;
> +			/* Check if VXLAN item is used to describe protocol.
> +			 * If yes, both spec and mask should be NULL.
> +			 * If no, both spec and mask shouldn't be NULL.
> +			 */
> +			if ((!nvgre_spec && nvgre_mask) ||
> +			    (nvgre_spec && !nvgre_mask)) {
> +				rte_flow_error_set(error, EINVAL,
> +					   RTE_FLOW_ERROR_TYPE_ITEM,
> +					   item,
> +					   "Invalid VXLAN item");
> +				return -rte_errno;
> +			}
> +
> +			break;
> +		default:
> +			rte_flow_error_set(error, EINVAL,
> +					   RTE_FLOW_ERROR_TYPE_ITEM,
> +					   item,
> +					   "Invalid mask no exist");
> +			break;
> +		}
> +	}
> +	return input_set;
> +}
> +
> +static int ice_flow_valid_inset(const struct rte_flow_item pattern[],
> +			uint64_t inset, struct rte_flow_error *error)
> +{
> +	uint64_t fields;
> +
> +	/* get valid field */
> +	fields = ice_get_flow_field(pattern, error);
> +	if ((!fields) || (fields && (!inset))) {
> +		rte_flow_error_set(error, EINVAL,
> +				   RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
> +				   pattern,
> +				   "Invalid input set");
> +		return -rte_errno;
> +	}
> +
> +	return 0;
> +}
> +
> +static int ice_flow_valid_action(const struct rte_flow_action *actions,
> +				       struct rte_flow_error *error)
> +{
> +	switch (actions->type) {
> +	case RTE_FLOW_ACTION_TYPE_QUEUE:
> +		break;
> +	case RTE_FLOW_ACTION_TYPE_DROP:
> +		break;
> +	default:
> +		rte_flow_error_set(error, EINVAL,
> +				   RTE_FLOW_ERROR_TYPE_ACTION, actions,
> +				   "Invalid action.");
> +		return -rte_errno;
> +	}
> +
> +	return 0;
> +}
> +
> +static int
> +ice_flow_validate(__rte_unused struct rte_eth_dev *dev,
> +		   const struct rte_flow_attr *attr,
> +		   const struct rte_flow_item pattern[],
> +		   const struct rte_flow_action actions[],
> +		   struct rte_flow_error *error)
> +{
> +	uint64_t inset = 0;
> +	int ret = ICE_ERR_NOT_SUPPORTED;
> +
> +	if (!pattern) {
> +		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM_NUM,
> +				   NULL, "NULL pattern.");
> +		return -rte_errno;
> +	}
> +
> +	if (!actions) {
> +		rte_flow_error_set(error, EINVAL,
> +				   RTE_FLOW_ERROR_TYPE_ACTION_NUM,
> +				   NULL, "NULL action.");
> +		return -rte_errno;
> +	}
> +
> +	if (!attr) {
> +		rte_flow_error_set(error, EINVAL,
> +				   RTE_FLOW_ERROR_TYPE_ATTR,
> +				   NULL, "NULL attribute.");
> +		return -rte_errno;
> +	}
> +
> +	ret = ice_flow_valid_attr(attr, error);
> +	if (!ret)
> +		return ret;
> +
> +	inset = ice_flow_valid_pattern(pattern, error);
> +	if (!inset)
> +		return -rte_errno;
> +
> +	ret = ice_flow_valid_inset(pattern, inset, error);
> +	if (ret)
> +		return ret;
> +
> +	ret = ice_flow_valid_action(actions, error);
> +	if (ret)
> +		return ret;
> +
> +	return 0;
> +}
> +
> +static struct rte_flow *
> +ice_flow_create(struct rte_eth_dev *dev,
> +		 const struct rte_flow_attr *attr,
> +		 const struct rte_flow_item pattern[],
> +		 const struct rte_flow_action actions[],
> +		 struct rte_flow_error *error)
> +{
> +	struct ice_pf *pf = ICE_DEV_PRIVATE_TO_PF(dev->data->dev_private);
> +	struct rte_flow *flow = NULL;
> +	int ret;
> +
> +	flow = rte_zmalloc("ice_flow", sizeof(struct rte_flow), 0);
> +	if (!flow) {
> +		rte_flow_error_set(error, ENOMEM,
> +				   RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
> +				   "Failed to allocate memory");
> +		return flow;
> +	}
> +
> +	ret = ice_flow_validate(dev, attr, pattern, actions, error);
> +	if (ret < 0)
> +		return NULL;
> +
> +	ret = ice_create_switch_filter(pf, pattern, actions, flow, error);
> +	if (ret)
> +		goto free_flow;
> +
> +	TAILQ_INSERT_TAIL(&pf->flow_list, flow, node);
> +	return flow;
> +
> +free_flow:
> +	rte_flow_error_set(error, -ret,
> +			   RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
> +			   "Failed to create flow.");
> +	rte_free(flow);
> +	return NULL;
> +}
> +
> +static int
> +ice_flow_destroy(struct rte_eth_dev *dev,
> +		 struct rte_flow *flow,
> +		 struct rte_flow_error *error)
> +{
> +	struct ice_pf *pf = ICE_DEV_PRIVATE_TO_PF(dev->data->dev_private);
> +	int ret = 0;
> +
> +	ret = ice_destroy_switch_filter(pf, flow, error);
> +
> +	if (!ret) {
> +		TAILQ_REMOVE(&pf->flow_list, flow, node);
> +		rte_free(flow);
> +	} else
> +		rte_flow_error_set(error, -ret,
> +				   RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
> +				   "Failed to destroy flow.");
> +
> +	return ret;
> +}
> +
> +static int
> +ice_flow_flush(struct rte_eth_dev *dev,
> +	       struct rte_flow_error *error)
> +{
> +	struct ice_pf *pf = ICE_DEV_PRIVATE_TO_PF(dev->data->dev_private);
> +	struct rte_flow *p_flow;
> +	int ret;
> +
> +	TAILQ_FOREACH(p_flow, &pf->flow_list, node) {
> +		ret = ice_flow_destroy(dev, p_flow, error);
> +		if (ret) {
> +			rte_flow_error_set(error, -ret,
> +					   RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
> +					   "Failed to flush SW flows.");
> +			return -rte_errno;
> +		}
> +	}
> +
> +	return ret;
> +}
> diff --git a/drivers/net/ice/ice_generic_flow.h b/drivers/net/ice/ice_generic_flow.h
> new file mode 100644
> index 0000000..ed7f3fe
> --- /dev/null
> +++ b/drivers/net/ice/ice_generic_flow.h
> @@ -0,0 +1,654 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(c) 2019 Intel Corporation
> + */
> +
> +#ifndef _ICE_GENERIC_FLOW_H_
> +#define _ICE_GENERIC_FLOW_H_
> +
> +#include <rte_flow_driver.h>
> +
> +struct ice_flow_pattern {
> +	enum rte_flow_item_type *items;
> +	uint64_t sw_fields;
> +};
> +
> +#define ICE_INSET_NONE            0x00000000000000000ULL
> +
> +/* bit0 ~ bit 7 */
> +#define ICE_INSET_SMAC            0x0000000000000001ULL
> +#define ICE_INSET_DMAC            0x0000000000000002ULL
> +#define ICE_INSET_ETHERTYPE       0x0000000000000020ULL
> +
> +/* bit 8 ~ bit 15 */
> +#define ICE_INSET_IPV4_SRC        0x0000000000000100ULL
> +#define ICE_INSET_IPV4_DST        0x0000000000000200ULL
> +#define ICE_INSET_IPV6_SRC        0x0000000000000400ULL
> +#define ICE_INSET_IPV6_DST        0x0000000000000800ULL
> +#define ICE_INSET_SRC_PORT        0x0000000000001000ULL
> +#define ICE_INSET_DST_PORT        0x0000000000002000ULL
> +#define ICE_INSET_ARP             0x0000000000004000ULL
> +
> +/* bit 16 ~ bit 31 */
> +#define ICE_INSET_IPV4_TOS        0x0000000000010000ULL
> +#define ICE_INSET_IPV4_PROTO      0x0000000000020000ULL
> +#define ICE_INSET_IPV4_TTL        0x0000000000040000ULL
> +#define ICE_INSET_IPV6_NEXT_HDR   0x0000000000200000ULL
> +#define ICE_INSET_IPV6_HOP_LIMIT  0x0000000000400000ULL
> +#define ICE_INSET_ICMP            0x0000000001000000ULL
> +#define ICE_INSET_ICMP6           0x0000000002000000ULL
> +
> +/* bit 32 ~ bit 47, tunnel fields */
> +#define ICE_INSET_TUN_SMAC           0x0000000100000000ULL
> +#define ICE_INSET_TUN_DMAC           0x0000000200000000ULL
> +#define ICE_INSET_TUN_IPV4_SRC       0x0000000400000000ULL
> +#define ICE_INSET_TUN_IPV4_DST       0x0000000800000000ULL
> +#define ICE_INSET_TUN_IPV4_TTL       0x0000001000000000ULL
> +#define ICE_INSET_TUN_IPV4_PROTO     0x0000002000000000ULL
> +#define ICE_INSET_TUN_IPV6_SRC       0x0000004000000000ULL
> +#define ICE_INSET_TUN_IPV6_DST       0x0000008000000000ULL
> +#define ICE_INSET_TUN_IPV6_TTL       0x0000010000000000ULL
> +#define ICE_INSET_TUN_IPV6_PROTO     0x0000020000000000ULL
> +#define ICE_INSET_TUN_SRC_PORT       0x0000040000000000ULL
> +#define ICE_INSET_TUN_DST_PORT       0x0000080000000000ULL
> +#define ICE_INSET_TUN_ID             0x0000100000000000ULL
> +
> +/* bit 48 ~ bit 55 */
> +#define ICE_INSET_LAST_ETHER_TYPE 0x0001000000000000ULL
> +
> +#define ICE_FLAG_VLAN_INNER  0x00000001ULL
> +#define ICE_FLAG_VLAN_OUTER  0x00000002ULL
> +
> +#define INSET_ETHER ( \
> +	ICE_INSET_DMAC | ICE_INSET_SMAC | ICE_INSET_ETHERTYPE)
> +#define INSET_MAC_IPV4 ( \
> +	ICE_INSET_IPV4_DST | ICE_INSET_IPV4_SRC | \
> +	ICE_INSET_IPV4_PROTO | ICE_INSET_IPV4_TOS)
> +#define INSET_MAC_IPV4_L4 ( \
> +	ICE_INSET_IPV4_DST | ICE_INSET_IPV4_SRC | \
> +	ICE_INSET_IPV4_TOS | ICE_INSET_DST_PORT | \
> +	ICE_INSET_SRC_PORT)
> +#define INSET_MAC_IPV4_ICMP ( \
> +	ICE_INSET_IPV4_DST | ICE_INSET_IPV4_SRC | \
> +	ICE_INSET_IPV4_TOS | ICE_INSET_ICMP)
> +#define INSET_MAC_IPV6 ( \
> +	ICE_INSET_IPV6_DST | ICE_INSET_IPV6_SRC | \
> +	ICE_INSET_IPV6_NEXT_HDR | ICE_INSET_IPV6_HOP_LIMIT)
> +#define INSET_MAC_IPV6_L4 ( \
> +	ICE_INSET_IPV6_DST | ICE_INSET_IPV6_SRC | \
> +	ICE_INSET_IPV6_HOP_LIMIT | ICE_INSET_DST_PORT | \
> +	ICE_INSET_SRC_PORT)
> +#define INSET_MAC_IPV6_ICMP ( \
> +	ICE_INSET_IPV6_DST | ICE_INSET_IPV6_SRC | \
> +	ICE_INSET_IPV6_HOP_LIMIT | ICE_INSET_ICMP6)
> +#define INSET_TUNNEL_IPV4_TYPE1 ( \
> +	ICE_INSET_TUN_IPV4_SRC | ICE_INSET_TUN_IPV4_DST | \
> +	ICE_INSET_TUN_IPV4_TTL | ICE_INSET_TUN_IPV4_PROTO)
> +#define INSET_TUNNEL_IPV4_TYPE2 ( \
> +	ICE_INSET_TUN_IPV4_SRC | ICE_INSET_TUN_IPV4_DST | \
> +	ICE_INSET_TUN_IPV4_TTL | ICE_INSET_TUN_IPV4_PROTO | \
> +	ICE_INSET_TUN_SRC_PORT | ICE_INSET_TUN_DST_PORT)
> +#define INSET_TUNNEL_IPV4_TYPE3 ( \
> +	ICE_INSET_TUN_IPV4_SRC | ICE_INSET_TUN_IPV4_DST | \
> +	ICE_INSET_TUN_IPV4_TTL | ICE_INSET_ICMP)
> +#define INSET_TUNNEL_IPV6_TYPE1 ( \
> +	ICE_INSET_TUN_IPV6_SRC | ICE_INSET_TUN_IPV6_DST | \
> +	ICE_INSET_TUN_IPV6_TTL | ICE_INSET_TUN_IPV6_PROTO)
> +#define INSET_TUNNEL_IPV6_TYPE2 ( \
> +	ICE_INSET_TUN_IPV6_SRC | ICE_INSET_TUN_IPV6_DST | \
> +	ICE_INSET_TUN_IPV6_TTL | ICE_INSET_TUN_IPV6_PROTO | \
> +	ICE_INSET_TUN_SRC_PORT | ICE_INSET_TUN_DST_PORT)
> +#define INSET_TUNNEL_IPV6_TYPE3 ( \
> +	ICE_INSET_TUN_IPV6_SRC | ICE_INSET_TUN_IPV6_DST | \
> +	ICE_INSET_TUN_IPV6_TTL | ICE_INSET_ICMP6)
> +
> +/* L2 */
> +static enum rte_flow_item_type pattern_ethertype[] = {
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +/* non-tunnel IPv4 */
> +static enum rte_flow_item_type pattern_ipv4[] = {
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_udp[] = {
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_UDP,
> +	RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_tcp[] = {
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_TCP,
> +	RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_sctp[] = {
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_SCTP,
> +	RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_icmp[] = {
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_ICMP,
> +	RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +/* non-tunnel IPv6 */
> +static enum rte_flow_item_type pattern_ipv6[] = {
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV6,
> +	RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv6_udp[] = {
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV6,
> +	RTE_FLOW_ITEM_TYPE_UDP,
> +	RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv6_tcp[] = {
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV6,
> +	RTE_FLOW_ITEM_TYPE_TCP,
> +	RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv6_sctp[] = {
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV6,
> +	RTE_FLOW_ITEM_TYPE_SCTP,
> +	RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv6_icmp6[] = {
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV6,
> +	RTE_FLOW_ITEM_TYPE_ICMP6,
> +	RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +/* IPv4 VXLAN IPv4 */
> +static enum rte_flow_item_type pattern_ipv4_vxlan_ipv4[] = {
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_UDP,
> +	RTE_FLOW_ITEM_TYPE_VXLAN,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_vxlan_ipv4_udp[] = {
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_UDP,
> +	RTE_FLOW_ITEM_TYPE_VXLAN,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_UDP,
> +	RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_vxlan_ipv4_tcp[] = {
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_UDP,
> +	RTE_FLOW_ITEM_TYPE_VXLAN,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_TCP,
> +	RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_vxlan_ipv4_sctp[] = {
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_UDP,
> +	RTE_FLOW_ITEM_TYPE_VXLAN,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_SCTP,
> +	RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_vxlan_ipv4_icmp[] = {
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_UDP,
> +	RTE_FLOW_ITEM_TYPE_VXLAN,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_ICMP,
> +	RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +/* IPv4 VXLAN MAC IPv4 */
> +static enum rte_flow_item_type pattern_ipv4_vxlan_eth_ipv4[] = {
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_UDP,
> +	RTE_FLOW_ITEM_TYPE_VXLAN,
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_vxlan_eth_ipv4_udp[] = {
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_UDP,
> +	RTE_FLOW_ITEM_TYPE_VXLAN,
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_UDP,
> +	RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_vxlan_eth_ipv4_tcp[] = {
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_UDP,
> +	RTE_FLOW_ITEM_TYPE_VXLAN,
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_TCP,
> +	RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_vxlan_eth_ipv4_sctp[] = {
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_UDP,
> +	RTE_FLOW_ITEM_TYPE_VXLAN,
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_SCTP,
> +	RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_vxlan_eth_ipv4_icmp[] = {
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_UDP,
> +	RTE_FLOW_ITEM_TYPE_VXLAN,
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_ICMP,
> +	RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +/* IPv4 VXLAN IPv6 */
> +static enum rte_flow_item_type pattern_ipv4_vxlan_ipv6[] = {
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_UDP,
> +	RTE_FLOW_ITEM_TYPE_VXLAN,
> +	RTE_FLOW_ITEM_TYPE_IPV6,
> +	RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_vxlan_ipv6_udp[] = {
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_UDP,
> +	RTE_FLOW_ITEM_TYPE_VXLAN,
> +	RTE_FLOW_ITEM_TYPE_IPV6,
> +	RTE_FLOW_ITEM_TYPE_UDP,
> +	RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_vxlan_ipv6_tcp[] = {
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_UDP,
> +	RTE_FLOW_ITEM_TYPE_VXLAN,
> +	RTE_FLOW_ITEM_TYPE_IPV6,
> +	RTE_FLOW_ITEM_TYPE_TCP,
> +	RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_vxlan_ipv6_sctp[] = {
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_UDP,
> +	RTE_FLOW_ITEM_TYPE_VXLAN,
> +	RTE_FLOW_ITEM_TYPE_IPV6,
> +	RTE_FLOW_ITEM_TYPE_SCTP,
> +	RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_vxlan_ipv6_icmp[] = {
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_UDP,
> +	RTE_FLOW_ITEM_TYPE_VXLAN,
> +	RTE_FLOW_ITEM_TYPE_IPV6,
> +	RTE_FLOW_ITEM_TYPE_ICMP,
> +	RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +/* IPv4 VXLAN MAC IPv6 */
> +static enum rte_flow_item_type pattern_ipv4_vxlan_eth_ipv6[] = {
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_UDP,
> +	RTE_FLOW_ITEM_TYPE_VXLAN,
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV6,
> +	RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_vxlan_eth_ipv6_udp[] = {
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_UDP,
> +	RTE_FLOW_ITEM_TYPE_VXLAN,
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV6,
> +	RTE_FLOW_ITEM_TYPE_UDP,
> +	RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_vxlan_eth_ipv6_tcp[] = {
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_UDP,
> +	RTE_FLOW_ITEM_TYPE_VXLAN,
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV6,
> +	RTE_FLOW_ITEM_TYPE_TCP,
> +	RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_vxlan_eth_ipv6_sctp[] = {
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_UDP,
> +	RTE_FLOW_ITEM_TYPE_VXLAN,
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV6,
> +	RTE_FLOW_ITEM_TYPE_SCTP,
> +	RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_vxlan_eth_ipv6_icmp[] = {
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_UDP,
> +	RTE_FLOW_ITEM_TYPE_VXLAN,
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV6,
> +	RTE_FLOW_ITEM_TYPE_ICMP,
> +	RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +/* IPv4 NVGRE IPv4 */
> +static enum rte_flow_item_type pattern_ipv4_nvgre_ipv4[] = {
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_UDP,
> +	RTE_FLOW_ITEM_TYPE_VXLAN,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_nvgre_ipv4_udp[] = {
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_UDP,
> +	RTE_FLOW_ITEM_TYPE_VXLAN,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_UDP,
> +	RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_nvgre_ipv4_tcp[] = {
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_UDP,
> +	RTE_FLOW_ITEM_TYPE_VXLAN,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_TCP,
> +	RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_nvgre_ipv4_sctp[] = {
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_UDP,
> +	RTE_FLOW_ITEM_TYPE_VXLAN,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_SCTP,
> +	RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_nvgre_ipv4_icmp[] = {
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_UDP,
> +	RTE_FLOW_ITEM_TYPE_VXLAN,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_ICMP,
> +	RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +/* IPv4 NVGRE MAC IPv4 */
> +static enum rte_flow_item_type pattern_ipv4_nvgre_eth_ipv4[] = {
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_UDP,
> +	RTE_FLOW_ITEM_TYPE_VXLAN,
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_nvgre_eth_ipv4_udp[] = {
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_UDP,
> +	RTE_FLOW_ITEM_TYPE_VXLAN,
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_UDP,
> +	RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_nvgre_eth_ipv4_tcp[] = {
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_UDP,
> +	RTE_FLOW_ITEM_TYPE_VXLAN,
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_TCP,
> +	RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_nvgre_eth_ipv4_sctp[] = {
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_UDP,
> +	RTE_FLOW_ITEM_TYPE_VXLAN,
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_SCTP,
> +	RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_nvgre_eth_ipv4_icmp[] = {
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_UDP,
> +	RTE_FLOW_ITEM_TYPE_VXLAN,
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_ICMP,
> +	RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +/* IPv4 NVGRE IPv6 */
> +static enum rte_flow_item_type pattern_ipv4_nvgre_ipv6[] = {
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_UDP,
> +	RTE_FLOW_ITEM_TYPE_VXLAN,
> +	RTE_FLOW_ITEM_TYPE_IPV6,
> +	RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_nvgre_ipv6_udp[] = {
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_UDP,
> +	RTE_FLOW_ITEM_TYPE_VXLAN,
> +	RTE_FLOW_ITEM_TYPE_IPV6,
> +	RTE_FLOW_ITEM_TYPE_UDP,
> +	RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_nvgre_ipv6_tcp[] = {
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_UDP,
> +	RTE_FLOW_ITEM_TYPE_VXLAN,
> +	RTE_FLOW_ITEM_TYPE_IPV6,
> +	RTE_FLOW_ITEM_TYPE_TCP,
> +	RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_nvgre_ipv6_sctp[] = {
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_UDP,
> +	RTE_FLOW_ITEM_TYPE_VXLAN,
> +	RTE_FLOW_ITEM_TYPE_IPV6,
> +	RTE_FLOW_ITEM_TYPE_SCTP,
> +	RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_nvgre_ipv6_icmp[] = {
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_UDP,
> +	RTE_FLOW_ITEM_TYPE_VXLAN,
> +	RTE_FLOW_ITEM_TYPE_IPV6,
> +	RTE_FLOW_ITEM_TYPE_ICMP,
> +	RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +/* IPv4 NVGRE MAC IPv6 */
> +static enum rte_flow_item_type pattern_ipv4_nvgre_eth_ipv6[] = {
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_UDP,
> +	RTE_FLOW_ITEM_TYPE_VXLAN,
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV6,
> +	RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_nvgre_eth_ipv6_udp[] = {
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_UDP,
> +	RTE_FLOW_ITEM_TYPE_VXLAN,
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV6,
> +	RTE_FLOW_ITEM_TYPE_UDP,
> +	RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_nvgre_eth_ipv6_tcp[] = {
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_UDP,
> +	RTE_FLOW_ITEM_TYPE_VXLAN,
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV6,
> +	RTE_FLOW_ITEM_TYPE_TCP,
> +	RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_nvgre_eth_ipv6_sctp[] = {
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_UDP,
> +	RTE_FLOW_ITEM_TYPE_VXLAN,
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV6,
> +	RTE_FLOW_ITEM_TYPE_SCTP,
> +	RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_nvgre_eth_ipv6_icmp[] = {
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV4,
> +	RTE_FLOW_ITEM_TYPE_UDP,
> +	RTE_FLOW_ITEM_TYPE_VXLAN,
> +	RTE_FLOW_ITEM_TYPE_ETH,
> +	RTE_FLOW_ITEM_TYPE_IPV6,
> +	RTE_FLOW_ITEM_TYPE_ICMP,
> +	RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static struct ice_flow_pattern ice_supported_patterns[] = {
> +	{pattern_ethertype, INSET_ETHER},
> +	{pattern_ipv4, INSET_MAC_IPV4},
> +	{pattern_ipv4_udp, INSET_MAC_IPV4_L4},
> +	{pattern_ipv4_sctp, INSET_MAC_IPV4_L4},
> +	{pattern_ipv4_tcp, INSET_MAC_IPV4_L4},
> +	{pattern_ipv4_icmp, INSET_MAC_IPV4_ICMP},
> +	{pattern_ipv6, INSET_MAC_IPV6},
> +	{pattern_ipv6_udp, INSET_MAC_IPV6_L4},
> +	{pattern_ipv6_sctp, INSET_MAC_IPV6_L4},
> +	{pattern_ipv6_tcp, INSET_MAC_IPV6_L4},
> +	{pattern_ipv6_icmp6, INSET_MAC_IPV6_ICMP},
> +	{pattern_ipv4_vxlan_ipv4, INSET_TUNNEL_IPV4_TYPE1},
> +	{pattern_ipv4_vxlan_ipv4_udp, INSET_TUNNEL_IPV4_TYPE2},
> +	{pattern_ipv4_vxlan_ipv4_tcp, INSET_TUNNEL_IPV4_TYPE2},
> +	{pattern_ipv4_vxlan_ipv4_sctp, INSET_TUNNEL_IPV4_TYPE2},
> +	{pattern_ipv4_vxlan_ipv4_icmp, INSET_TUNNEL_IPV4_TYPE3},
> +	{pattern_ipv4_vxlan_eth_ipv4, INSET_TUNNEL_IPV4_TYPE1},
> +	{pattern_ipv4_vxlan_eth_ipv4_udp, INSET_TUNNEL_IPV4_TYPE2},
> +	{pattern_ipv4_vxlan_eth_ipv4_tcp, INSET_TUNNEL_IPV4_TYPE2},
> +	{pattern_ipv4_vxlan_eth_ipv4_sctp, INSET_TUNNEL_IPV4_TYPE2},
> +	{pattern_ipv4_vxlan_eth_ipv4_icmp, INSET_TUNNEL_IPV4_TYPE3},
> +	{pattern_ipv4_vxlan_ipv6, INSET_TUNNEL_IPV6_TYPE1},
> +	{pattern_ipv4_vxlan_ipv6_udp, INSET_TUNNEL_IPV6_TYPE2},
> +	{pattern_ipv4_vxlan_ipv6_tcp, INSET_TUNNEL_IPV6_TYPE2},
> +	{pattern_ipv4_vxlan_ipv6_sctp, INSET_TUNNEL_IPV6_TYPE2},
> +	{pattern_ipv4_vxlan_ipv6_icmp, INSET_TUNNEL_IPV6_TYPE3},
> +	{pattern_ipv4_vxlan_eth_ipv6, INSET_TUNNEL_IPV6_TYPE1},
> +	{pattern_ipv4_vxlan_eth_ipv6_udp, INSET_TUNNEL_IPV6_TYPE2},
> +	{pattern_ipv4_vxlan_eth_ipv6_tcp, INSET_TUNNEL_IPV6_TYPE2},
> +	{pattern_ipv4_vxlan_eth_ipv6_sctp, INSET_TUNNEL_IPV6_TYPE2},
> +	{pattern_ipv4_vxlan_eth_ipv6_icmp, INSET_TUNNEL_IPV6_TYPE3},
> +	{pattern_ipv4_nvgre_ipv4, INSET_TUNNEL_IPV4_TYPE1},
> +	{pattern_ipv4_nvgre_ipv4_udp, INSET_TUNNEL_IPV4_TYPE2},
> +	{pattern_ipv4_nvgre_ipv4_tcp, INSET_TUNNEL_IPV4_TYPE2},
> +	{pattern_ipv4_nvgre_ipv4_sctp, INSET_TUNNEL_IPV4_TYPE2},
> +	{pattern_ipv4_nvgre_ipv4_icmp, INSET_TUNNEL_IPV4_TYPE3},
> +	{pattern_ipv4_nvgre_eth_ipv4, INSET_TUNNEL_IPV4_TYPE1},
> +	{pattern_ipv4_nvgre_eth_ipv4_udp, INSET_TUNNEL_IPV4_TYPE2},
> +	{pattern_ipv4_nvgre_eth_ipv4_tcp, INSET_TUNNEL_IPV4_TYPE2},
> +	{pattern_ipv4_nvgre_eth_ipv4_sctp, INSET_TUNNEL_IPV4_TYPE2},
> +	{pattern_ipv4_nvgre_eth_ipv4_icmp, INSET_TUNNEL_IPV4_TYPE3},
> +	{pattern_ipv4_nvgre_ipv6, INSET_TUNNEL_IPV6_TYPE1},
> +	{pattern_ipv4_nvgre_ipv6_udp, INSET_TUNNEL_IPV6_TYPE2},
> +	{pattern_ipv4_nvgre_ipv6_tcp, INSET_TUNNEL_IPV6_TYPE2},
> +	{pattern_ipv4_nvgre_ipv6_sctp, INSET_TUNNEL_IPV6_TYPE2},
> +	{pattern_ipv4_nvgre_ipv6_icmp, INSET_TUNNEL_IPV6_TYPE3},
> +	{pattern_ipv4_nvgre_eth_ipv6, INSET_TUNNEL_IPV6_TYPE1},
> +	{pattern_ipv4_nvgre_eth_ipv6_udp, INSET_TUNNEL_IPV6_TYPE2},
> +	{pattern_ipv4_nvgre_eth_ipv6_tcp, INSET_TUNNEL_IPV6_TYPE2},
> +	{pattern_ipv4_nvgre_eth_ipv6_sctp, INSET_TUNNEL_IPV6_TYPE2},
> +	{pattern_ipv4_nvgre_eth_ipv6_icmp, INSET_TUNNEL_IPV6_TYPE3},
> +};
> +
> +#endif
> diff --git a/drivers/net/ice/meson.build b/drivers/net/ice/meson.build
> index 8697676..18180b9 100644
> --- a/drivers/net/ice/meson.build
> +++ b/drivers/net/ice/meson.build
> @@ -8,6 +8,7 @@ sources = files(
>  	'ice_ethdev.c',
>  	'ice_rxtx.c',
>  	'ice_switch_filter.c'

Missing a comma here.

> +	'ice_generic_flow.c'
>  	)
>  
>  deps += ['hash']

^ permalink raw reply

* Re: [PATCH] mfd: da9063: occupy second I2C address, too
From: Lee Jones @ 2019-06-20 13:33 UTC (permalink / raw)
  To: Steve Twiss
  Cc: wsa+renesas@sang-engineering.com, bgolaszewski@baylibre.com,
	kieran.bingham+renesas@ideasonboard.com,
	linux-kernel@vger.kernel.org, linux-renesas-soc@vger.kernel.org,
	peda@axentia.se, Support Opensource
In-Reply-To: <AM6PR10MB2181D2A08D98FB9F8092EC8DFEE40@AM6PR10MB2181.EURPRD10.PROD.OUTLOOK.COM>

On Thu, 20 Jun 2019, Steve Twiss wrote:

> On 20 June 2019 13:29, Lee Jones wrote:
> 
> > Subject: Re: [PATCH] mfd: da9063: occupy second I2C address, too
> > 
> > Why isn't this reply attached (threaded) to the patch.
> 
> My apologies. It wasn't my intention to split Wolfram's original e-mail thread.
> 
> I don't usually reply using the mailto: link from lore when creating e-mails.
> Outlook mustn't support the In-Reply-To header.
> 
> I'll figure out a different way to reply in future.
> 
> > Is your mailer broken?
> 
> It's Windows

Say no more. ;)

-- 
Lee Jones [李琼斯]
Linaro Services Technical Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply

* Re: [PATCH 3/3] mmc: sdhci-of-arasan: Add support for ZynqMP Platform Tap Delays Setup
From: Ulf Hansson @ 2019-06-20 13:33 UTC (permalink / raw)
  To: Manish Narani
  Cc: Michal Simek, Rob Herring, Mark Rutland, Adrian Hunter,
	Rajan Vaja, Jolly Shah, Nava kishore Manne, Olof Johansson,
	linux-mmc@vger.kernel.org, DTML, Linux Kernel Mailing List,
	Linux ARM
In-Reply-To: <MN2PR02MB602935234A2A779B5A05CD63C1E40@MN2PR02MB6029.namprd02.prod.outlook.com>

On Thu, 20 Jun 2019 at 10:14, Manish Narani <MNARANI@xilinx.com> wrote:
>
> Hi Uffe,
>
>
> > -----Original Message-----
> > From: Ulf Hansson <ulf.hansson@linaro.org>
> > Sent: Wednesday, June 19, 2019 7:09 PM
> > To: Manish Narani <MNARANI@xilinx.com>
> > Cc: Michal Simek <michals@xilinx.com>; Rob Herring <robh+dt@kernel.org>;
> > Mark Rutland <mark.rutland@arm.com>; Adrian Hunter
> > <adrian.hunter@intel.com>; Rajan Vaja <RAJANV@xilinx.com>; Jolly Shah
> > <JOLLYS@xilinx.com>; Nava kishore Manne <navam@xilinx.com>; Olof
> > Johansson <olof@lixom.net>; linux-mmc@vger.kernel.org; DTML
> > <devicetree@vger.kernel.org>; Linux Kernel Mailing List <linux-
> > kernel@vger.kernel.org>; Linux ARM <linux-arm-kernel@lists.infradead.org>
> > Subject: Re: [PATCH 3/3] mmc: sdhci-of-arasan: Add support for ZynqMP
> > Platform Tap Delays Setup
> >
> > On Wed, 19 Jun 2019 at 10:40, Manish Narani <MNARANI@xilinx.com> wrote:
> > >
> > > Hi Uffe,
> > >
> > >
> > > > -----Original Message-----
> > > > From: Ulf Hansson <ulf.hansson@linaro.org>
> > > > Sent: Monday, June 17, 2019 5:51 PM
> > > [...]
> > > >
> > > > The "const struct zynqmp_eemi_ops *eemi_ops; should then be moved into
> > > > a clock provider specific struct, which is assigned when calling
> > > > sdhci_arasan_register_sdclk. I understand that all the clock data is
> > > > folded into struct sdhci_arasan_data today, but I think that should be
> > > > moved into a "sub-struct" for the clock specifics.
> > > >
> > > > Moreover, when registering the clock, we should convert from using
> > > > devm_clk_register() into devm_clk_hw_register() as the first one is
> > > > now deprecated.
> > >
> > > Just a query here:
> > > When we switch to using devm_clk_hw_register() here, it will register the
> > clk_hw and return int.
> > > Is there a way we can get the clk (related to the clk_hw registered) from the
> > > clock framework?
> > > I am asking this because we will need that clk pointer while calling
> > clk_set_phase() function.
> >
> > I assume devm_clk_get() should work fine?
>
> This clock does not come through ZynqMP Clock framework. We are initializing it in this 'sdhci-of-arasan' driver and getting only the clock name from "clock_output_names" property. So I think devm_clk_get() will not work here for our case.

Well, I guess you need to register an OF clock provider to allow the
clock lookup to work. Apologize, but I don't have the time, currently
to point you in the exact direction.

However, in principle, my point is, there should be no difference
whether the clock is registered via the "ZynqMP Clock framework" or
via the mmc driver. The *clk_get() thing need to work, otherwise I
consider the clock registration in the mmc driver to be a hack. If you
see what I mean.

> I have gone through the clock framework and I found one function which may be used to create clock from clock hw, that is ' clk_hw_create_clk()' which can be used from our driver, however this needs change in the clock framework as below :
>
> ---
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index aa51756..4dc69ff 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -3420,6 +3420,7 @@ struct clk *clk_hw_create_clk(struct device *dev, struct clk_hw *hw,
>
>         return clk;
>  }
> +EXPORT_SYMBOL_GPL(clk_hw_create_clk);
>
>  static int clk_cpy_name(const char **dst_p, const char *src, bool must_exist)
>  {
> diff --git a/drivers/clk/clk.h b/drivers/clk/clk.h
> index d8400d6..2319899 100644
> --- a/drivers/clk/clk.h
> +++ b/drivers/clk/clk.h
> @@ -22,17 +22,9 @@ static inline struct clk_hw *of_clk_get_hw(struct device_node *np,
>  struct clk_hw *clk_find_hw(const char *dev_id, const char *con_id);
>
>  #ifdef CONFIG_COMMON_CLK
> -struct clk *clk_hw_create_clk(struct device *dev, struct clk_hw *hw,
> -                             const char *dev_id, const char *con_id);
>  void __clk_put(struct clk *clk);
>  #else
>  /* All these casts to avoid ifdefs in clkdev... */
> -static inline struct clk *
> -clk_hw_create_clk(struct device *dev, struct clk_hw *hw, const char *dev_id,
> -                 const char *con_id)
> -{
> -       return (struct clk *)hw;
> -}
>  static struct clk_hw *__clk_get_hw(struct clk *clk)
>  {
>         return (struct clk_hw *)clk;
> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index f689fc5..d3f60fe 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -18,6 +18,7 @@
>
>  struct device;
>  struct clk;
> +struct clk_hw;
>  struct device_node;
>  struct of_phandle_args;
>
> @@ -934,4 +935,15 @@ static inline struct clk *of_clk_get_from_provider(struct of_phandle_args *clksp
>  }
>  #endif
>
> +#ifdef CONFIG_COMMON_CLK
> +struct clk *clk_hw_create_clk(struct device *dev, struct clk_hw *hw,
> +                             const char *dev_id, const char *con_id);
> +#else
> +static inline struct clk *
> +clk_hw_create_clk(struct device *dev, struct clk_hw *hw, const char *dev_id,
> +                 const char *con_id)
> +{
> +       return (struct clk *)hw;
> +}
> +#endif
>  #endif
> ---
>
> This change should help other drivers (outside 'drivers/clk/') as well for getting the clock created from clk_hw.
> Is this fine to do?

I think this is the wrong approach, see why further above.

Kind regards
Uffe

^ permalink raw reply

* Applied "regulator: da9061/62: Adjust LDO voltage selection minimum value" to the regulator tree
From: Mark Brown @ 2019-06-20 13:32 UTC (permalink / raw)
  To: Felix Riemann
  Cc: Felix Riemann, Lee Jones, Liam Girdwood, linux-kernel, LKML,
	Mark Brown, Steve Twiss, Support Opensource
In-Reply-To: <20190620074042.E1E803FB4A@swsrvapps-01.diasemi.com>

The patch

   regulator: da9061/62: Adjust LDO voltage selection minimum value

has been applied to the regulator tree at

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator.git for-5.3

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

From fd5d10059d5ead12dd12f05ae6d96e70d1fac3df Mon Sep 17 00:00:00 2001
From: Felix Riemann <felix.riemann@sma.de>
Date: Thu, 20 Jun 2019 08:45:00 +0100
Subject: [PATCH] regulator: da9061/62: Adjust LDO voltage selection minimum
 value

According to the DA9061 and DA9062 datasheets the LDO voltage selection
registers have a lower value of 0x02. This applies to voltage registers
VLDO1_A, VLDO2_A, VLDO3_A and VLDO4_A. This linear offset of 0x02 was
previously not observed by the driver, causing the LDO output voltage to
be systematically lower by two steps (= 0.1V).

This patch fixes the minimum linear selector offset by setting it to a
value of 2 and increases the n_voltages by the same amount allowing
voltages in the range 0x02 -> 0.9V to 0x38 -> 3.6V to be correctly
selected. Also fixes an incorrect calculaton for the n_voltages value in
the regulator LDO2.

These fixes effect all LDO regulators for DA9061 and DA9062.

Acked-by: Steve Twiss <stwiss.opensource@diasemi.com>
Tested-by: Steve Twiss <stwiss.opensource@diasemi.com>
Signed-off-by: Felix Riemann <felix.riemann@sma.de>
Signed-off-by: Steve Twiss <stwiss.opensource@diasemi.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 drivers/regulator/da9062-regulator.c | 40 +++++++++++++++++-----------
 include/linux/mfd/da9062/registers.h |  3 +++
 2 files changed, 27 insertions(+), 16 deletions(-)

diff --git a/drivers/regulator/da9062-regulator.c b/drivers/regulator/da9062-regulator.c
index a02e0488410f..2ffc64622451 100644
--- a/drivers/regulator/da9062-regulator.c
+++ b/drivers/regulator/da9062-regulator.c
@@ -493,12 +493,13 @@ static const struct da9062_regulator_info local_da9061_regulator_info[] = {
 		.desc.ops = &da9062_ldo_ops,
 		.desc.min_uV = (900) * 1000,
 		.desc.uV_step = (50) * 1000,
-		.desc.n_voltages = ((3600) - (900))/(50) + 1,
+		.desc.n_voltages = ((3600) - (900))/(50) + 1
+				+ DA9062AA_VLDO_A_MIN_SEL,
 		.desc.enable_reg = DA9062AA_LDO1_CONT,
 		.desc.enable_mask = DA9062AA_LDO1_EN_MASK,
 		.desc.vsel_reg = DA9062AA_VLDO1_A,
 		.desc.vsel_mask = DA9062AA_VLDO1_A_MASK,
-		.desc.linear_min_sel = 0,
+		.desc.linear_min_sel = DA9062AA_VLDO_A_MIN_SEL,
 		.sleep = REG_FIELD(DA9062AA_VLDO1_A,
 			__builtin_ffs((int)DA9062AA_LDO1_SL_A_MASK) - 1,
 			sizeof(unsigned int) * 8 -
@@ -525,12 +526,13 @@ static const struct da9062_regulator_info local_da9061_regulator_info[] = {
 		.desc.ops = &da9062_ldo_ops,
 		.desc.min_uV = (900) * 1000,
 		.desc.uV_step = (50) * 1000,
-		.desc.n_voltages = ((3600) - (600))/(50) + 1,
+		.desc.n_voltages = ((3600) - (900))/(50) + 1
+				+ DA9062AA_VLDO_A_MIN_SEL,
 		.desc.enable_reg = DA9062AA_LDO2_CONT,
 		.desc.enable_mask = DA9062AA_LDO2_EN_MASK,
 		.desc.vsel_reg = DA9062AA_VLDO2_A,
 		.desc.vsel_mask = DA9062AA_VLDO2_A_MASK,
-		.desc.linear_min_sel = 0,
+		.desc.linear_min_sel = DA9062AA_VLDO_A_MIN_SEL,
 		.sleep = REG_FIELD(DA9062AA_VLDO2_A,
 			__builtin_ffs((int)DA9062AA_LDO2_SL_A_MASK) - 1,
 			sizeof(unsigned int) * 8 -
@@ -557,12 +559,13 @@ static const struct da9062_regulator_info local_da9061_regulator_info[] = {
 		.desc.ops = &da9062_ldo_ops,
 		.desc.min_uV = (900) * 1000,
 		.desc.uV_step = (50) * 1000,
-		.desc.n_voltages = ((3600) - (900))/(50) + 1,
+		.desc.n_voltages = ((3600) - (900))/(50) + 1
+				+ DA9062AA_VLDO_A_MIN_SEL,
 		.desc.enable_reg = DA9062AA_LDO3_CONT,
 		.desc.enable_mask = DA9062AA_LDO3_EN_MASK,
 		.desc.vsel_reg = DA9062AA_VLDO3_A,
 		.desc.vsel_mask = DA9062AA_VLDO3_A_MASK,
-		.desc.linear_min_sel = 0,
+		.desc.linear_min_sel = DA9062AA_VLDO_A_MIN_SEL,
 		.sleep = REG_FIELD(DA9062AA_VLDO3_A,
 			__builtin_ffs((int)DA9062AA_LDO3_SL_A_MASK) - 1,
 			sizeof(unsigned int) * 8 -
@@ -589,12 +592,13 @@ static const struct da9062_regulator_info local_da9061_regulator_info[] = {
 		.desc.ops = &da9062_ldo_ops,
 		.desc.min_uV = (900) * 1000,
 		.desc.uV_step = (50) * 1000,
-		.desc.n_voltages = ((3600) - (900))/(50) + 1,
+		.desc.n_voltages = ((3600) - (900))/(50) + 1
+				+ DA9062AA_VLDO_A_MIN_SEL,
 		.desc.enable_reg = DA9062AA_LDO4_CONT,
 		.desc.enable_mask = DA9062AA_LDO4_EN_MASK,
 		.desc.vsel_reg = DA9062AA_VLDO4_A,
 		.desc.vsel_mask = DA9062AA_VLDO4_A_MASK,
-		.desc.linear_min_sel = 0,
+		.desc.linear_min_sel = DA9062AA_VLDO_A_MIN_SEL,
 		.sleep = REG_FIELD(DA9062AA_VLDO4_A,
 			__builtin_ffs((int)DA9062AA_LDO4_SL_A_MASK) - 1,
 			sizeof(unsigned int) * 8 -
@@ -769,12 +773,13 @@ static const struct da9062_regulator_info local_da9062_regulator_info[] = {
 		.desc.ops = &da9062_ldo_ops,
 		.desc.min_uV = (900) * 1000,
 		.desc.uV_step = (50) * 1000,
-		.desc.n_voltages = ((3600) - (900))/(50) + 1,
+		.desc.n_voltages = ((3600) - (900))/(50) + 1
+				+ DA9062AA_VLDO_A_MIN_SEL,
 		.desc.enable_reg = DA9062AA_LDO1_CONT,
 		.desc.enable_mask = DA9062AA_LDO1_EN_MASK,
 		.desc.vsel_reg = DA9062AA_VLDO1_A,
 		.desc.vsel_mask = DA9062AA_VLDO1_A_MASK,
-		.desc.linear_min_sel = 0,
+		.desc.linear_min_sel = DA9062AA_VLDO_A_MIN_SEL,
 		.sleep = REG_FIELD(DA9062AA_VLDO1_A,
 			__builtin_ffs((int)DA9062AA_LDO1_SL_A_MASK) - 1,
 			sizeof(unsigned int) * 8 -
@@ -801,12 +806,13 @@ static const struct da9062_regulator_info local_da9062_regulator_info[] = {
 		.desc.ops = &da9062_ldo_ops,
 		.desc.min_uV = (900) * 1000,
 		.desc.uV_step = (50) * 1000,
-		.desc.n_voltages = ((3600) - (600))/(50) + 1,
+		.desc.n_voltages = ((3600) - (900))/(50) + 1
+				+ DA9062AA_VLDO_A_MIN_SEL,
 		.desc.enable_reg = DA9062AA_LDO2_CONT,
 		.desc.enable_mask = DA9062AA_LDO2_EN_MASK,
 		.desc.vsel_reg = DA9062AA_VLDO2_A,
 		.desc.vsel_mask = DA9062AA_VLDO2_A_MASK,
-		.desc.linear_min_sel = 0,
+		.desc.linear_min_sel = DA9062AA_VLDO_A_MIN_SEL,
 		.sleep = REG_FIELD(DA9062AA_VLDO2_A,
 			__builtin_ffs((int)DA9062AA_LDO2_SL_A_MASK) - 1,
 			sizeof(unsigned int) * 8 -
@@ -833,12 +839,13 @@ static const struct da9062_regulator_info local_da9062_regulator_info[] = {
 		.desc.ops = &da9062_ldo_ops,
 		.desc.min_uV = (900) * 1000,
 		.desc.uV_step = (50) * 1000,
-		.desc.n_voltages = ((3600) - (900))/(50) + 1,
+		.desc.n_voltages = ((3600) - (900))/(50) + 1
+				+ DA9062AA_VLDO_A_MIN_SEL,
 		.desc.enable_reg = DA9062AA_LDO3_CONT,
 		.desc.enable_mask = DA9062AA_LDO3_EN_MASK,
 		.desc.vsel_reg = DA9062AA_VLDO3_A,
 		.desc.vsel_mask = DA9062AA_VLDO3_A_MASK,
-		.desc.linear_min_sel = 0,
+		.desc.linear_min_sel = DA9062AA_VLDO_A_MIN_SEL,
 		.sleep = REG_FIELD(DA9062AA_VLDO3_A,
 			__builtin_ffs((int)DA9062AA_LDO3_SL_A_MASK) - 1,
 			sizeof(unsigned int) * 8 -
@@ -865,12 +872,13 @@ static const struct da9062_regulator_info local_da9062_regulator_info[] = {
 		.desc.ops = &da9062_ldo_ops,
 		.desc.min_uV = (900) * 1000,
 		.desc.uV_step = (50) * 1000,
-		.desc.n_voltages = ((3600) - (900))/(50) + 1,
+		.desc.n_voltages = ((3600) - (900))/(50) + 1
+				+ DA9062AA_VLDO_A_MIN_SEL,
 		.desc.enable_reg = DA9062AA_LDO4_CONT,
 		.desc.enable_mask = DA9062AA_LDO4_EN_MASK,
 		.desc.vsel_reg = DA9062AA_VLDO4_A,
 		.desc.vsel_mask = DA9062AA_VLDO4_A_MASK,
-		.desc.linear_min_sel = 0,
+		.desc.linear_min_sel = DA9062AA_VLDO_A_MIN_SEL,
 		.sleep = REG_FIELD(DA9062AA_VLDO4_A,
 			__builtin_ffs((int)DA9062AA_LDO4_SL_A_MASK) - 1,
 			sizeof(unsigned int) * 8 -
diff --git a/include/linux/mfd/da9062/registers.h b/include/linux/mfd/da9062/registers.h
index fe04b708742b..2906bf6160fb 100644
--- a/include/linux/mfd/da9062/registers.h
+++ b/include/linux/mfd/da9062/registers.h
@@ -797,6 +797,9 @@
 #define DA9062AA_BUCK3_SL_A_SHIFT	7
 #define DA9062AA_BUCK3_SL_A_MASK	BIT(7)
 
+/* DA9062AA_VLDO[1-4]_A common */
+#define DA9062AA_VLDO_A_MIN_SEL	2
+
 /* DA9062AA_VLDO1_A = 0x0A9 */
 #define DA9062AA_VLDO1_A_SHIFT		0
 #define DA9062AA_VLDO1_A_MASK		0x3f
-- 
2.20.1


^ permalink raw reply related

* [RFC PATCH] arm64: dts: fsl: wandboard: Add a device tree for the PICO-PI-IMX8M
From: Andra Danciu @ 2019-06-20 13:32 UTC (permalink / raw)
  To: robh+dt, mark.rutland, shawnguo
  Cc: leoyang.li, aisheng.dong, sriram.dash, pramod.kumar_1,
	bhaskar.upadhaya, vabhav.sharma, pankaj.bansal, richard.hu,
	l.stach, ping.bai, manivannan.sadhasivam, devicetree,
	linux-kernel, daniel.baluta

From: Richard Hu <richard.hu@technexion.com>

The current level of support yields a working console and is able to boot
userspace from an initial ramdisk copied via u-boot in RAM.

Additional subsystems that are active :
	- Ethernet
	- USB

Cc: Daniel Baluta <daniel.baluta@nxp.com>
Signed-off-by: Richard Hu <richard.hu@technexion.com>
Signed-off-by: Andra Danciu <andradanciu1997@gmail.com>
---
 I am using pico-pi-8mxm board to work on my project for Google Summer of Code.
 This is based on patches from https://github.com/wandboard-org.

 arch/arm64/boot/dts/freescale/Makefile       |   1 +
 arch/arm64/boot/dts/freescale/wand-pi-8m.dts | 590 +++++++++++++++++++++++++++
 2 files changed, 591 insertions(+)
 create mode 100644 arch/arm64/boot/dts/freescale/wand-pi-8m.dts

diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile
index 984554343c83..5904d6a8a033 100644
--- a/arch/arm64/boot/dts/freescale/Makefile
+++ b/arch/arm64/boot/dts/freescale/Makefile
@@ -23,3 +23,4 @@ dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-lx2160a-rdb.dtb
 dtb-$(CONFIG_ARCH_MXC) += imx8mm-evk.dtb
 dtb-$(CONFIG_ARCH_MXC) += imx8mq-evk.dtb
 dtb-$(CONFIG_ARCH_MXC) += imx8qxp-mek.dtb
+dtb-$(CONFIG_ARCH_MXC) += wand-pi-8m.dtb
diff --git a/arch/arm64/boot/dts/freescale/wand-pi-8m.dts b/arch/arm64/boot/dts/freescale/wand-pi-8m.dts
new file mode 100644
index 000000000000..9f7121014722
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/wand-pi-8m.dts
@@ -0,0 +1,590 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2018 Wandboard, Org.
+ * Copyright 2017 NXP
+ *
+ * Author: Richard Hu <hakahu@gmail.com>
+ */
+
+/dts-v1/;
+
+#include "imx8mq.dtsi"
+
+/ {
+	model = "WAND-PI-8M";
+	compatible = "wand,imx8mq-wand-pi", "fsl,imx8mq";
+
+	chosen {
+		bootargs = "console=ttymxc0,115200 earlycon=ec_imx6q,0x30860000,115200";
+		stdout-path = &uart1;
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		reg_usb_otg_vbus: usb_otg_vbus {
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_otg_vbus>;
+			compatible = "regulator-fixed";
+			regulator-name = "usb_otg_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			gpio = <&gpio3 14 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	regulator-virtuals {
+		compatible = "simple-bus";
+
+		virt-buck1 {
+			compatible = "regulator-virtual";
+			virtual-supply = "buck1";
+		};
+		virt-buck2 {
+			compatible = "regulator-virtual";
+			virtual-supply = "buck2";
+		};
+		virt-buck3 {
+			compatible = "regulator-virtual";
+			virtual-supply = "buck3";
+		};
+		virt-buck4 {
+			compatible = "regulator-virtual";
+			virtual-supply = "buck4";
+		};
+		virt-buck5 {
+			compatible = "regulator-virtual";
+			virtual-supply = "buck5";
+		};
+		virt-buck6 {
+			compatible = "regulator-virtual";
+			virtual-supply = "buck6";
+		};
+		virt-buck7 {
+			compatible = "regulator-virtual";
+			virtual-supply = "buck7";
+		};
+		virt-buck8 {
+			compatible = "regulator-virtual";
+			virtual-supply = "buck8";
+		};
+		virt-ldo1 {
+			compatible = "regulator-virtual";
+			virtual-supply = "ldo1";
+		};
+		virt-ldo2 {
+			compatible = "regulator-virtual";
+			virtual-supply = "ldo2";
+		};
+		virt-ldo3 {
+			compatible = "regulator-virtual";
+			virtual-supply = "ldo3";
+		};
+		virt-ldo4 {
+			compatible = "regulator-virtual";
+			virtual-supply = "ldo4";
+		};
+		virt-ldo5 {
+			compatible = "regulator-virtual";
+			virtual-supply = "ldo5";
+		};
+		virt-ldo6 {
+			compatible = "regulator-virtual";
+			virtual-supply = "ldo6";
+		};
+		virt-ldo7 {
+			compatible = "regulator-virtual";
+			virtual-supply = "ldo7";
+		};
+	};
+
+	gpio-edm {
+		compatible = "gpio-edm";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_wifi_ctrl>;
+
+		gpio_wifi_wl_reg_on {
+			label = "WL_REG_ON";
+			gpios = <&gpio3 0 GPIO_ACTIVE_LOW>;
+			dir   = "out";
+		};
+
+		gpio_wifi_pwr_en {
+			label = "WIFI_PWR_EN";
+			gpios = <&gpio3 15 GPIO_ACTIVE_LOW>;
+			dir   = "out";
+		};
+	};
+};
+
+&iomuxc {
+	pinctrl-names = "default";
+
+	wand-pi-8m {
+		pinctrl_otg_vbus: otgvbusgrp {
+			fsl,pins = <
+				MX8MQ_IOMUXC_NAND_DQS_GPIO3_IO14		0x19   /* USB OTG VBUS Enable */
+			>;
+		};
+
+		pinctrl_csi1: csi1grp {
+			fsl,pins = <
+				MX8MQ_IOMUXC_NAND_DATA01_GPIO3_IO7		0x19   /* CSI P1 PWDN */
+				MX8MQ_IOMUXC_GPIO1_IO12_GPIO1_IO12		0x19   /* CSI nRST */
+				MX8MQ_IOMUXC_GPIO1_IO15_CCMSRCGPCMIX_CLKO2	0x59
+			>;
+		};
+
+		pinctrl_enet_3v3: enet3v3grp {
+			fsl,pins = <
+				MX8MQ_IOMUXC_GPIO1_IO00_GPIO1_IO0		0x19
+			>;
+		};
+
+		pinctrl_fec1: fec1grp {
+			fsl,pins = <
+				MX8MQ_IOMUXC_ENET_MDC_ENET1_MDC		0x3
+				MX8MQ_IOMUXC_ENET_MDIO_ENET1_MDIO	0x23
+				MX8MQ_IOMUXC_ENET_TD3_ENET1_RGMII_TD3	0x1f
+				MX8MQ_IOMUXC_ENET_TD2_ENET1_RGMII_TD2	0x1f
+				MX8MQ_IOMUXC_ENET_TD1_ENET1_RGMII_TD1	0x1f
+				MX8MQ_IOMUXC_ENET_TD0_ENET1_RGMII_TD0	0x1f
+				MX8MQ_IOMUXC_ENET_RD3_ENET1_RGMII_RD3	0x91
+				MX8MQ_IOMUXC_ENET_RD2_ENET1_RGMII_RD2	0x91
+				MX8MQ_IOMUXC_ENET_RD1_ENET1_RGMII_RD1	0x91
+				MX8MQ_IOMUXC_ENET_RD0_ENET1_RGMII_RD0	0x91
+				MX8MQ_IOMUXC_ENET_TXC_ENET1_RGMII_TXC	0x1f
+				MX8MQ_IOMUXC_ENET_RXC_ENET1_RGMII_RXC	0x91
+				MX8MQ_IOMUXC_ENET_RX_CTL_ENET1_RGMII_RX_CTL	0x91
+				MX8MQ_IOMUXC_ENET_TX_CTL_ENET1_RGMII_TX_CTL	0x1f
+				MX8MQ_IOMUXC_GPIO1_IO09_GPIO1_IO9	0x19
+			>;
+		};
+
+		pinctrl_i2c1: i2c1grp {
+			fsl,pins = <
+				MX8MQ_IOMUXC_I2C1_SCL_I2C1_SCL			0x4000007f
+				MX8MQ_IOMUXC_I2C1_SDA_I2C1_SDA			0x4000007f
+			>;
+		};
+
+		pinctrl_i2c2: i2c2grp {
+			fsl,pins = <
+				MX8MQ_IOMUXC_I2C2_SCL_I2C2_SCL			0x4000007f
+				MX8MQ_IOMUXC_I2C2_SDA_I2C2_SDA			0x4000007f
+			>;
+		};
+
+		pinctrl_uart1: uart1grp {
+			fsl,pins = <
+				MX8MQ_IOMUXC_UART1_RXD_UART1_DCE_RX		0x49
+				MX8MQ_IOMUXC_UART1_TXD_UART1_DCE_TX		0x49
+			>;
+		};
+
+		pinctrl_uart2: uart2grp {
+			fsl,pins = <
+				MX8MQ_IOMUXC_UART2_RXD_UART2_DCE_RX		0x49
+				MX8MQ_IOMUXC_UART2_TXD_UART2_DCE_TX		0x49
+				MX8MQ_IOMUXC_UART4_RXD_UART2_DCE_CTS_B		0x49
+				MX8MQ_IOMUXC_UART4_TXD_UART2_DCE_RTS_B		0x49
+			>;
+		};
+
+		pinctrl_usdhc1: usdhc1grp {
+			fsl,pins = <
+				MX8MQ_IOMUXC_SD1_CLK_USDHC1_CLK			0x83
+				MX8MQ_IOMUXC_SD1_CMD_USDHC1_CMD			0xc3
+				MX8MQ_IOMUXC_SD1_DATA0_USDHC1_DATA0		0xc3
+				MX8MQ_IOMUXC_SD1_DATA1_USDHC1_DATA1		0xc3
+				MX8MQ_IOMUXC_SD1_DATA2_USDHC1_DATA2		0xc3
+				MX8MQ_IOMUXC_SD1_DATA3_USDHC1_DATA3		0xc3
+				MX8MQ_IOMUXC_SD1_DATA4_USDHC1_DATA4		0xc3
+				MX8MQ_IOMUXC_SD1_DATA5_USDHC1_DATA5		0xc3
+				MX8MQ_IOMUXC_SD1_DATA6_USDHC1_DATA6		0xc3
+				MX8MQ_IOMUXC_SD1_DATA7_USDHC1_DATA7		0xc3
+				MX8MQ_IOMUXC_SD1_STROBE_USDHC1_STROBE		0x83
+			>;
+		};
+
+		pinctrl_usdhc1_100mhz: usdhc1grp100mhz {
+			fsl,pins = <
+				MX8MQ_IOMUXC_SD1_CLK_USDHC1_CLK			0x85
+				MX8MQ_IOMUXC_SD1_CMD_USDHC1_CMD			0xc5
+				MX8MQ_IOMUXC_SD1_DATA0_USDHC1_DATA0		0xc5
+				MX8MQ_IOMUXC_SD1_DATA1_USDHC1_DATA1		0xc5
+				MX8MQ_IOMUXC_SD1_DATA2_USDHC1_DATA2		0xc5
+				MX8MQ_IOMUXC_SD1_DATA3_USDHC1_DATA3		0xc5
+				MX8MQ_IOMUXC_SD1_DATA4_USDHC1_DATA4		0xc5
+				MX8MQ_IOMUXC_SD1_DATA5_USDHC1_DATA5		0xc5
+				MX8MQ_IOMUXC_SD1_DATA6_USDHC1_DATA6		0xc5
+				MX8MQ_IOMUXC_SD1_DATA7_USDHC1_DATA7		0xc5
+				MX8MQ_IOMUXC_SD1_STROBE_USDHC1_STROBE		0x85
+			>;
+		};
+
+		pinctrl_usdhc1_200mhz: usdhc1grp200mhz {
+			fsl,pins = <
+				MX8MQ_IOMUXC_SD1_CLK_USDHC1_CLK			0x87
+				MX8MQ_IOMUXC_SD1_CMD_USDHC1_CMD			0xc7
+				MX8MQ_IOMUXC_SD1_DATA0_USDHC1_DATA0		0xc7
+				MX8MQ_IOMUXC_SD1_DATA1_USDHC1_DATA1		0xc7
+				MX8MQ_IOMUXC_SD1_DATA2_USDHC1_DATA2		0xc7
+				MX8MQ_IOMUXC_SD1_DATA3_USDHC1_DATA3		0xc7
+				MX8MQ_IOMUXC_SD1_DATA4_USDHC1_DATA4		0xc7
+				MX8MQ_IOMUXC_SD1_DATA5_USDHC1_DATA5		0xc7
+				MX8MQ_IOMUXC_SD1_DATA6_USDHC1_DATA6		0xc7
+				MX8MQ_IOMUXC_SD1_DATA7_USDHC1_DATA7		0xc7
+				MX8MQ_IOMUXC_SD1_STROBE_USDHC1_STROBE		0x87
+			>;
+		};
+
+		pinctrl_usdhc2_gpio: usdhc2grpgpio {
+			fsl,pins = <
+				MX8MQ_IOMUXC_SD2_CD_B_GPIO2_IO12	0x41
+			>;
+		};
+
+		pinctrl_usdhc2: usdhc2grp {
+			fsl,pins = <
+				MX8MQ_IOMUXC_SD2_CLK_USDHC2_CLK			0x83
+				MX8MQ_IOMUXC_SD2_CMD_USDHC2_CMD			0xc3
+				MX8MQ_IOMUXC_SD2_DATA0_USDHC2_DATA0		0xc3
+				MX8MQ_IOMUXC_SD2_DATA1_USDHC2_DATA1		0xc3
+				MX8MQ_IOMUXC_SD2_DATA2_USDHC2_DATA2		0xc3
+				MX8MQ_IOMUXC_SD2_DATA3_USDHC2_DATA3		0xc3
+				MX8MQ_IOMUXC_GPIO1_IO04_USDHC2_VSELECT		0xc1
+			>;
+		};
+
+		pinctrl_usdhc2_100mhz: usdhc2grp100mhz {
+			fsl,pins = <
+				MX8MQ_IOMUXC_SD2_CLK_USDHC2_CLK			0x85
+				MX8MQ_IOMUXC_SD2_CMD_USDHC2_CMD			0xc5
+				MX8MQ_IOMUXC_SD2_DATA0_USDHC2_DATA0		0xc5
+				MX8MQ_IOMUXC_SD2_DATA1_USDHC2_DATA1		0xc5
+				MX8MQ_IOMUXC_SD2_DATA2_USDHC2_DATA2		0xc5
+				MX8MQ_IOMUXC_SD2_DATA3_USDHC2_DATA3		0xc5
+				MX8MQ_IOMUXC_GPIO1_IO04_USDHC2_VSELECT		0xc1
+			>;
+		};
+
+		pinctrl_usdhc2_200mhz: usdhc2grp200mhz {
+			fsl,pins = <
+				MX8MQ_IOMUXC_SD2_CLK_USDHC2_CLK			0x87
+				MX8MQ_IOMUXC_SD2_CMD_USDHC2_CMD			0xc7
+				MX8MQ_IOMUXC_SD2_DATA0_USDHC2_DATA0		0xc7
+				MX8MQ_IOMUXC_SD2_DATA1_USDHC2_DATA1		0xc7
+				MX8MQ_IOMUXC_SD2_DATA2_USDHC2_DATA2		0xc7
+				MX8MQ_IOMUXC_SD2_DATA3_USDHC2_DATA3		0xc7
+				MX8MQ_IOMUXC_GPIO1_IO04_USDHC2_VSELECT		0xc1
+			>;
+		};
+
+		pinctrl_wdog: wdoggrp {
+			fsl,pins = <
+				MX8MQ_IOMUXC_GPIO1_IO02_WDOG1_WDOG_B 0xc6
+			>;
+		};
+
+		pinctrl_pmic: pmicirq {
+			fsl,pins = <
+				MX8MQ_IOMUXC_GPIO1_IO03_GPIO1_IO3	0x41
+			>;
+		};
+
+		pinctrl_wifi_ctrl: wifi_ctrlgrp {
+			fsl,pins = <
+				MX8MQ_IOMUXC_NAND_ALE_GPIO3_IO0		0x19 /* WL_REG_ON */
+				MX8MQ_IOMUXC_NAND_RE_B_GPIO3_IO15	0x19 /* WIFI_PWR_EN */
+			>;
+		};
+
+		pinctrl_tusb320_irq: tusb320_irqgrp {
+			fsl,pins = <
+				MX8MQ_IOMUXC_NAND_DATA00_GPIO3_IO6	0x41
+			>;
+		};
+
+		pinctrl_typec_ss_sel: typec_ss_selgrp {
+			fsl,pins = <
+				MX8MQ_IOMUXC_NAND_CLE_GPIO3_IO5		0x19
+			>;
+		};
+	};
+};
+
+&fec1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_fec1 &pinctrl_enet_3v3>;
+	phy-mode = "rgmii-id";
+	pinctrl-assert-gpios = <&gpio1 0 GPIO_ACTIVE_HIGH>;
+	phy-handle = <&ethphy0>;
+	fsl,magic-packet;
+	status = "okay";
+
+	mdio {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		ethphy0: ethernet-phy@1 {
+			compatible = "ethernet-phy-ieee802.3-c22";
+			reg = <1>;
+			at803x,led-act-blind-workaround;
+			at803x,eee-disabled;
+		};
+	};
+};
+
+&i2c1 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c1>;
+	status = "okay";
+
+	typec_tusb320:tusb320@47 {
+		compatible = "ti,tusb320";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_tusb320_irq &pinctrl_typec_ss_sel>;
+		reg = <0x47>;
+		vbus-supply = <&reg_usb_otg_vbus>;
+		ss-sel-gpios = <&gpio3 5 GPIO_ACTIVE_HIGH>;
+		tusb320,int-gpio = <&gpio3 6 GPIO_ACTIVE_LOW>;
+		tusb320,select-mode = <0>;
+		tusb320,dfp-power = <0>;
+	};
+
+	pmic: bd71837@4b {
+		reg = <0x4b>;
+		compatible = "rohm,bd71837";
+		/* PMIC BD71837 PMIC_nINT GPIO1_IO12 */
+		pinctrl-0 = <&pinctrl_pmic>;
+		gpio_intr = <&gpio1 3 GPIO_ACTIVE_LOW>;
+
+		bd71837,pmic-buck1-uses-i2c-dvs;
+		bd71837,pmic-buck1-dvs-voltage = <900000>, <850000>, <800000>; /* VDD_SOC: Run-Idle-Suspend */
+		bd71837,pmic-buck2-uses-i2c-dvs;
+		bd71837,pmic-buck2-dvs-voltage = <1000000>, <900000>, <0>; /* VDD_ARM: Run-Idle */
+		bd71837,pmic-buck3-uses-i2c-dvs;
+		bd71837,pmic-buck3-dvs-voltage = <1000000>, <0>, <0>; /* VDD_GPU: Run */
+		bd71837,pmic-buck4-uses-i2c-dvs;
+		bd71837,pmic-buck4-dvs-voltage = <1000000>, <0>, <0>; /* VDD_VPU: Run */
+
+		gpo {
+			rohm,drv = <0x0C>;	/* 0b0000_1100 all gpos with cmos output mode */
+		};
+
+		regulators {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			buck1_reg: regulator@0 {
+				reg = <0>;
+				regulator-compatible = "buck1";
+				regulator-min-microvolt = <700000>;
+				regulator-max-microvolt = <1300000>;
+				regulator-boot-on;
+				regulator-always-on;
+				regulator-ramp-delay = <1250>;
+			};
+
+			buck2_reg: regulator@1 {
+				reg = <1>;
+				regulator-compatible = "buck2";
+				regulator-min-microvolt = <700000>;
+				regulator-max-microvolt = <1300000>;
+				regulator-boot-on;
+				regulator-always-on;
+				regulator-ramp-delay = <1250>;
+			};
+
+			buck3_reg: regulator@2 {
+				reg = <2>;
+				regulator-compatible = "buck3";
+				regulator-min-microvolt = <700000>;
+				regulator-max-microvolt = <1300000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			buck4_reg: regulator@3 {
+				reg = <3>;
+				regulator-compatible = "buck4";
+				regulator-min-microvolt = <700000>;
+				regulator-max-microvolt = <1300000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			buck5_reg: regulator@4 {
+				reg = <4>;
+				regulator-compatible = "buck5";
+				regulator-min-microvolt = <700000>;
+				regulator-max-microvolt = <1350000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			buck6_reg: regulator@5 {
+				reg = <5>;
+				regulator-compatible = "buck6";
+				regulator-min-microvolt = <3000000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			buck7_reg: regulator@6 {
+				reg = <6>;
+				regulator-compatible = "buck7";
+				regulator-min-microvolt = <1605000>;
+				regulator-max-microvolt = <1995000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			buck8_reg: regulator@7 {
+				reg = <7>;
+				regulator-compatible = "buck8";
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <1400000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldo1_reg: regulator@8 {
+				reg = <8>;
+				regulator-compatible = "ldo1";
+				regulator-min-microvolt = <3000000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldo2_reg: regulator@9 {
+				reg = <9>;
+				regulator-compatible = "ldo2";
+				regulator-min-microvolt = <900000>;
+				regulator-max-microvolt = <900000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldo3_reg: regulator@10 {
+				reg = <10>;
+				regulator-compatible = "ldo3";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldo4_reg: regulator@11 {
+				reg = <11>;
+				regulator-compatible = "ldo4";
+				regulator-min-microvolt = <900000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldo5_reg: regulator@12 {
+				reg = <12>;
+				regulator-compatible = "ldo5";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldo6_reg: regulator@13 {
+				reg = <13>;
+				regulator-compatible = "ldo6";
+				regulator-min-microvolt = <900000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldo7_reg: regulator@14 {
+				reg = <14>;
+				regulator-compatible = "ldo7";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+		};
+	};
+};
+
+&i2c2 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2>;
+	status = "okay";
+};
+
+&uart1 { /* console */
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
+	status = "okay";
+};
+
+&usdhc1 {
+	pinctrl-names = "default", "state_100mhz", "state_200mhz";
+	pinctrl-0 = <&pinctrl_usdhc1>;
+	pinctrl-1 = <&pinctrl_usdhc1_100mhz>;
+	pinctrl-2 = <&pinctrl_usdhc1_200mhz>;
+	bus-width = <8>;
+	non-removable;
+	status = "okay";
+};
+
+&usdhc2 {
+	pinctrl-names = "default", "state_100mhz", "state_200mhz";
+	pinctrl-0 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_gpio>;
+	pinctrl-1 = <&pinctrl_usdhc2_100mhz>, <&pinctrl_usdhc2_gpio>;
+	pinctrl-2 = <&pinctrl_usdhc2_200mhz>, <&pinctrl_usdhc2_gpio>;
+	bus-width = <4>;
+	cd-gpios = <&gpio2 12 GPIO_ACTIVE_LOW>;
+	status = "okay";
+};
+
+&usb3_phy0 {
+	status = "okay";
+};
+
+&usb_dwc3_0 {
+	extcon = <&typec_tusb320>;
+	dr_mode = "otg";
+	status = "okay";
+};
+
+&usb3_phy1 {
+	status = "okay";
+};
+
+&usb_dwc3_1 {
+	status = "okay";
+	dr_mode = "host";
+};
+
+&wdog1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_wdog>;
+	fsl,ext-reset-output;
+	status = "okay";
+};
+
+&A53_0 {
+	operating-points = <
+		/* kHz    uV */
+		1500000 1000000
+		1300000 1000000
+		1000000 900000
+		800000  900000
+	>;
+};
-- 
2.11.0

^ permalink raw reply related

* Applied "regulator: s2mps11: Fix ERR_PTR dereference on GPIO lookup failure" to the regulator tree
From: Mark Brown @ 2019-06-20 13:32 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: Bartlomiej Zolnierkiewicz, Georg Waibel, Liam Girdwood,
	linux-kernel, linux-samsung-soc, Marek Szyprowski, Mark Brown,
	Sangbeom Kim, stable, stable
In-Reply-To: <1560948159-21926-1-git-send-email-krzk@kernel.org>

The patch

   regulator: s2mps11: Fix ERR_PTR dereference on GPIO lookup failure

has been applied to the regulator tree at

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator.git for-5.2

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

From 70ca117b02f3b1c8830fe95e4e3dea2937038e11 Mon Sep 17 00:00:00 2001
From: Krzysztof Kozlowski <krzk@kernel.org>
Date: Wed, 19 Jun 2019 14:42:39 +0200
Subject: [PATCH] regulator: s2mps11: Fix ERR_PTR dereference on GPIO lookup
 failure

If devm_gpiod_get_from_of_node() call returns ERR_PTR, it is assigned
into an array of GPIO descriptors and used later because such error is
not treated as critical thus it is not propagated back to the probe
function.

All code later expects that such GPIO descriptor is either a NULL or
proper value.  This later might lead to dereference of ERR_PTR.

Only devices with S2MPS14 flavor are affected (other do not control
regulators with GPIOs).

Fixes: 1c984942f0a4 ("regulator: s2mps11: Pass descriptor instead of GPIO number")
Cc: <stable@vger.kernel.org>
Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 drivers/regulator/s2mps11.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c
index 134c62db36c5..af9bf10b4c33 100644
--- a/drivers/regulator/s2mps11.c
+++ b/drivers/regulator/s2mps11.c
@@ -824,6 +824,7 @@ static void s2mps14_pmic_dt_parse_ext_control_gpio(struct platform_device *pdev,
 		if (IS_ERR(gpio[reg])) {
 			dev_err(&pdev->dev, "Failed to get control GPIO for %d/%s\n",
 				reg, rdata[reg].name);
+			gpio[reg] = NULL;
 			continue;
 		}
 		if (gpio[reg])
-- 
2.20.1


^ permalink raw reply related

* Applied "spi: fix ctrl->num_chipselect constraint" to the spi tree
From: Mark Brown @ 2019-06-20 13:32 UTC (permalink / raw)
  To: Tudor Ambarus
  Cc: broonie, linus.walleij, linux-kernel, linux-spi, Mark Brown,
	Nicolas.Ferre, Tudor.Ambarus
In-Reply-To: <20190619143820.4045-1-tudor.ambarus@microchip.com>

The patch

   spi: fix ctrl->num_chipselect constraint

has been applied to the spi tree at

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git for-5.3

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

From f9481b08220d7dc1ff21e296a330ee8b721b44e4 Mon Sep 17 00:00:00 2001
From: Tudor Ambarus <tudor.ambarus@microchip.com>
Date: Wed, 19 Jun 2019 14:38:28 +0000
Subject: [PATCH] spi: fix ctrl->num_chipselect constraint

at91sam9g25ek showed the following error at probe:
atmel_spi f0000000.spi: Using dma0chan2 (tx) and dma0chan3 (rx)
for DMA transfers
atmel_spi: probe of f0000000.spi failed with error -22

Commit 0a919ae49223 ("spi: Don't call spi_get_gpio_descs() before device name is set")
moved the calling of spi_get_gpio_descs() after ctrl->dev is set,
but didn't move the !ctrl->num_chipselect check. When there are
chip selects in the device tree, the spi-atmel driver lets the
SPI core discover them when registering the SPI master.
The ctrl->num_chipselect is thus expected to be set by
spi_get_gpio_descs().

Move the !ctlr->num_chipselect after spi_get_gpio_descs() as it was
before the aforementioned commit. While touching this block, get rid
of the explicit comparison with 0 and update the commenting style.

Fixes: 0a919ae49223 ("spi: Don't call spi_get_gpio_descs() before device name is set")
Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 drivers/spi/spi.c | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index a31e1e291335..80d2d14f6294 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -2375,11 +2375,6 @@ int spi_register_controller(struct spi_controller *ctlr)
 	if (status)
 		return status;
 
-	/* even if it's just one always-selected device, there must
-	 * be at least one chipselect
-	 */
-	if (ctlr->num_chipselect == 0)
-		return -EINVAL;
 	if (ctlr->bus_num >= 0) {
 		/* devices with a fixed bus num must check-in with the num */
 		mutex_lock(&board_lock);
@@ -2450,6 +2445,13 @@ int spi_register_controller(struct spi_controller *ctlr)
 		}
 	}
 
+	/*
+	 * Even if it's just one always-selected device, there must
+	 * be at least one chipselect.
+	 */
+	if (!ctlr->num_chipselect)
+		return -EINVAL;
+
 	status = device_add(&ctlr->dev);
 	if (status < 0) {
 		/* free bus id */
-- 
2.20.1


^ permalink raw reply related


This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.