Commit 6accc376 authored by Kent Gibson's avatar Kent Gibson Committed by Bartosz Golaszewski
Browse files

gpiolib: cdev: use blocking notifier call chain instead of atomic



Replace usage of atomic_notifier_call_chain with
blocking_notifier_call_chain as the notifier function,
lineinfo_changed_notify, calls gpio_desc_to_lineinfo,
which calls pinctrl_gpio_can_use_line, which can sleep.

The chain isn't being called from an atomic context so the
the blocking notifier is a suitable substitute.

Signed-off-by: default avatarKent Gibson <warthog618@gmail.com>
Signed-off-by: default avatarBartosz Golaszewski <bgolaszewski@baylibre.com>
parent 0cdc85a3
Loading
Loading
Loading
Loading
+12 −12
Original line number Diff line number Diff line
@@ -158,7 +158,7 @@ static long linehandle_set_config(struct linehandle_state *lh,
				return ret;
		}

		atomic_notifier_call_chain(&desc->gdev->notifier,
		blocking_notifier_call_chain(&desc->gdev->notifier,
					     GPIOLINE_CHANGED_CONFIG, desc);
	}
	return 0;
@@ -325,7 +325,7 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip)
				goto out_free_descs;
		}

		atomic_notifier_call_chain(&desc->gdev->notifier,
		blocking_notifier_call_chain(&desc->gdev->notifier,
					     GPIOLINE_CHANGED_REQUESTED, desc);

		dev_dbg(&gdev->dev, "registered chardev handle for line %d\n",
@@ -674,7 +674,7 @@ static int lineevent_create(struct gpio_device *gdev, void __user *ip)
	if (ret)
		goto out_free_desc;

	atomic_notifier_call_chain(&desc->gdev->notifier,
	blocking_notifier_call_chain(&desc->gdev->notifier,
				     GPIOLINE_CHANGED_REQUESTED, desc);

	le->irq = gpiod_to_irq(desc);
@@ -1049,7 +1049,7 @@ static int gpio_chrdev_open(struct inode *inode, struct file *file)
	priv->gdev = gdev;

	priv->lineinfo_changed_nb.notifier_call = lineinfo_changed_notify;
	ret = atomic_notifier_chain_register(&gdev->notifier,
	ret = blocking_notifier_chain_register(&gdev->notifier,
					       &priv->lineinfo_changed_nb);
	if (ret)
		goto out_free_bitmap;
@@ -1064,7 +1064,7 @@ static int gpio_chrdev_open(struct inode *inode, struct file *file)
	return ret;

out_unregister_notifier:
	atomic_notifier_chain_unregister(&gdev->notifier,
	blocking_notifier_chain_unregister(&gdev->notifier,
					   &priv->lineinfo_changed_nb);
out_free_bitmap:
	bitmap_free(priv->watched_lines);
@@ -1085,7 +1085,7 @@ static int gpio_chrdev_release(struct inode *inode, struct file *file)
	struct gpio_device *gdev = priv->gdev;

	bitmap_free(priv->watched_lines);
	atomic_notifier_chain_unregister(&gdev->notifier,
	blocking_notifier_chain_unregister(&gdev->notifier,
					   &priv->lineinfo_changed_nb);
	put_device(&gdev->dev);
	kfree(priv);
+7 −7
Original line number Diff line number Diff line
@@ -615,7 +615,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,

	spin_unlock_irqrestore(&gpio_lock, flags);

	ATOMIC_INIT_NOTIFIER_HEAD(&gdev->notifier);
	BLOCKING_INIT_NOTIFIER_HEAD(&gdev->notifier);

#ifdef CONFIG_PINCTRL
	INIT_LIST_HEAD(&gdev->pin_ranges);
@@ -2049,7 +2049,7 @@ static bool gpiod_free_commit(struct gpio_desc *desc)
	}

	spin_unlock_irqrestore(&gpio_lock, flags);
	atomic_notifier_call_chain(&desc->gdev->notifier,
	blocking_notifier_call_chain(&desc->gdev->notifier,
				     GPIOLINE_CHANGED_RELEASED, desc);

	return ret;
@@ -3927,7 +3927,7 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev,
		return ERR_PTR(ret);
	}

	atomic_notifier_call_chain(&desc->gdev->notifier,
	blocking_notifier_call_chain(&desc->gdev->notifier,
				     GPIOLINE_CHANGED_REQUESTED, desc);

	return desc;
@@ -3995,7 +3995,7 @@ struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode,
		return ERR_PTR(ret);
	}

	atomic_notifier_call_chain(&desc->gdev->notifier,
	blocking_notifier_call_chain(&desc->gdev->notifier,
				     GPIOLINE_CHANGED_REQUESTED, desc);

	return desc;
+1 −1
Original line number Diff line number Diff line
@@ -56,7 +56,7 @@ struct gpio_device {
	const char		*label;
	void			*data;
	struct list_head        list;
	struct atomic_notifier_head notifier;
	struct blocking_notifier_head notifier;

#ifdef CONFIG_PINCTRL
	/*