diff options
author | Benjamin Tissoires <benjamin.tissoires@redhat.com> | 2016-10-13 14:10:40 +0200 |
---|---|---|
committer | Wolfram Sang <wsa@the-dreams.de> | 2016-11-24 16:22:06 +0100 |
commit | 4d5538f5882a6b67eefbab0f0a3a67ce811621aa (patch) | |
tree | 1a5e7055d2db7d178fd178c44740170eeec60228 /drivers/i2c/i2c-smbus.c | |
parent | c912a25a5a12a497bb47068e3d42d7c9b67bde12 (diff) | |
download | linux-4d5538f5882a6b67eefbab0f0a3a67ce811621aa.tar.bz2 |
i2c: use an IRQ to report Host Notify events, not alert
The current SMBus Host Notify implementation relies on .alert() to
relay its notifications. However, the use cases where SMBus Host
Notify is needed currently is to signal data ready on touchpads.
This is closer to an IRQ than a custom API through .alert().
Given that the 2 touchpad manufacturers (Synaptics and Elan) that
use SMBus Host Notify don't put any data in the SMBus payload, the
concept actually matches one to one.
Benefits are multiple:
- simpler code and API: the client will just have an IRQ, and
nothing needs to be added in the adapter beside internally
enabling it.
- no more specific workqueue, the threading is handled by IRQ core
directly (when required)
- no more races when removing the device (the drivers are already
required to disable irq on remove)
- simpler handling for drivers: use plain regular IRQs
- no more dependency on i2c-smbus for i2c-i801 (and any other adapter)
- the IRQ domain is created automatically when the adapter exports
the Host Notify capability
- the IRQ are assign only if ACPI, OF and the caller did not assign
one already
- the domain is automatically destroyed on remove
- fewer lines of code (minus 20, yeah!)
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
Diffstat (limited to 'drivers/i2c/i2c-smbus.c')
-rw-r--r-- | drivers/i2c/i2c-smbus.c | 102 |
1 files changed, 0 insertions, 102 deletions
diff --git a/drivers/i2c/i2c-smbus.c b/drivers/i2c/i2c-smbus.c index b0d2679c60d1..f9271c713d20 100644 --- a/drivers/i2c/i2c-smbus.c +++ b/drivers/i2c/i2c-smbus.c @@ -241,108 +241,6 @@ int i2c_handle_smbus_alert(struct i2c_client *ara) } EXPORT_SYMBOL_GPL(i2c_handle_smbus_alert); -static void smbus_host_notify_work(struct work_struct *work) -{ - struct alert_data alert; - struct i2c_adapter *adapter; - unsigned long flags; - u16 payload; - u8 addr; - struct smbus_host_notify *data; - - data = container_of(work, struct smbus_host_notify, work); - - spin_lock_irqsave(&data->lock, flags); - payload = data->payload; - addr = data->addr; - adapter = data->adapter; - - /* clear the pending bit and release the spinlock */ - data->pending = false; - spin_unlock_irqrestore(&data->lock, flags); - - if (!adapter || !addr) - return; - - alert.type = I2C_PROTOCOL_SMBUS_HOST_NOTIFY; - alert.addr = addr; - alert.data = payload; - - device_for_each_child(&adapter->dev, &alert, smbus_do_alert); -} - -/** - * i2c_setup_smbus_host_notify - Allocate a new smbus_host_notify for the given - * I2C adapter. - * @adapter: the adapter we want to associate a Host Notify function - * - * Returns a struct smbus_host_notify pointer on success, and NULL on failure. - * The resulting smbus_host_notify must not be freed afterwards, it is a - * managed resource already. - */ -struct smbus_host_notify *i2c_setup_smbus_host_notify(struct i2c_adapter *adap) -{ - struct smbus_host_notify *host_notify; - - host_notify = devm_kzalloc(&adap->dev, sizeof(struct smbus_host_notify), - GFP_KERNEL); - if (!host_notify) - return NULL; - - host_notify->adapter = adap; - - spin_lock_init(&host_notify->lock); - INIT_WORK(&host_notify->work, smbus_host_notify_work); - - return host_notify; -} -EXPORT_SYMBOL_GPL(i2c_setup_smbus_host_notify); - -/** - * i2c_handle_smbus_host_notify - Forward a Host Notify event to the correct - * I2C client. - * @host_notify: the struct host_notify attached to the relevant adapter - * @addr: the I2C address of the notifying device - * @data: the payload of the notification - * Context: can't sleep - * - * Helper function to be called from an I2C bus driver's interrupt - * handler. It will schedule the Host Notify work, in turn calling the - * corresponding I2C device driver's alert function. - * - * host_notify should be a valid pointer previously returned by - * i2c_setup_smbus_host_notify(). - */ -int i2c_handle_smbus_host_notify(struct smbus_host_notify *host_notify, - unsigned short addr, unsigned int data) -{ - unsigned long flags; - struct i2c_adapter *adapter; - - if (!host_notify || !host_notify->adapter) - return -EINVAL; - - adapter = host_notify->adapter; - - spin_lock_irqsave(&host_notify->lock, flags); - - if (host_notify->pending) { - spin_unlock_irqrestore(&host_notify->lock, flags); - dev_warn(&adapter->dev, "Host Notify already scheduled.\n"); - return -EBUSY; - } - - host_notify->payload = data; - host_notify->addr = addr; - - /* Mark that there is a pending notification and release the lock */ - host_notify->pending = true; - spin_unlock_irqrestore(&host_notify->lock, flags); - - return schedule_work(&host_notify->work); -} -EXPORT_SYMBOL_GPL(i2c_handle_smbus_host_notify); - module_i2c_driver(smbalert_driver); MODULE_AUTHOR("Jean Delvare <jdelvare@suse.de>"); |