|
@@ -25,8 +25,6 @@
|
|
|
#include <linux/workqueue.h>
|
|
|
|
|
|
struct i2c_smbus_alert {
|
|
|
- unsigned int alert_edge_triggered:1;
|
|
|
- int irq;
|
|
|
struct work_struct alert;
|
|
|
struct i2c_client *ara; /* Alert response address */
|
|
|
};
|
|
@@ -72,13 +70,12 @@ static int smbus_do_alert(struct device *dev, void *addrp)
|
|
|
* The alert IRQ handler needs to hand work off to a task which can issue
|
|
|
* SMBus calls, because those sleeping calls can't be made in IRQ context.
|
|
|
*/
|
|
|
-static void smbus_alert(struct work_struct *work)
|
|
|
+static irqreturn_t smbus_alert(int irq, void *d)
|
|
|
{
|
|
|
- struct i2c_smbus_alert *alert;
|
|
|
+ struct i2c_smbus_alert *alert = d;
|
|
|
struct i2c_client *ara;
|
|
|
unsigned short prev_addr = 0; /* Not a valid address */
|
|
|
|
|
|
- alert = container_of(work, struct i2c_smbus_alert, alert);
|
|
|
ara = alert->ara;
|
|
|
|
|
|
for (;;) {
|
|
@@ -115,21 +112,17 @@ static void smbus_alert(struct work_struct *work)
|
|
|
prev_addr = data.addr;
|
|
|
}
|
|
|
|
|
|
- /* We handled all alerts; re-enable level-triggered IRQs */
|
|
|
- if (!alert->alert_edge_triggered)
|
|
|
- enable_irq(alert->irq);
|
|
|
+ return IRQ_HANDLED;
|
|
|
}
|
|
|
|
|
|
-static irqreturn_t smbalert_irq(int irq, void *d)
|
|
|
+static void smbalert_work(struct work_struct *work)
|
|
|
{
|
|
|
- struct i2c_smbus_alert *alert = d;
|
|
|
+ struct i2c_smbus_alert *alert;
|
|
|
+
|
|
|
+ alert = container_of(work, struct i2c_smbus_alert, alert);
|
|
|
|
|
|
- /* Disable level-triggered IRQs until we handle them */
|
|
|
- if (!alert->alert_edge_triggered)
|
|
|
- disable_irq_nosync(irq);
|
|
|
+ smbus_alert(0, alert);
|
|
|
|
|
|
- schedule_work(&alert->alert);
|
|
|
- return IRQ_HANDLED;
|
|
|
}
|
|
|
|
|
|
/* Setup SMBALERT# infrastructure */
|
|
@@ -139,28 +132,28 @@ static int smbalert_probe(struct i2c_client *ara,
|
|
|
struct i2c_smbus_alert_setup *setup = dev_get_platdata(&ara->dev);
|
|
|
struct i2c_smbus_alert *alert;
|
|
|
struct i2c_adapter *adapter = ara->adapter;
|
|
|
- int res;
|
|
|
+ int res, irq;
|
|
|
|
|
|
alert = devm_kzalloc(&ara->dev, sizeof(struct i2c_smbus_alert),
|
|
|
GFP_KERNEL);
|
|
|
if (!alert)
|
|
|
return -ENOMEM;
|
|
|
|
|
|
- alert->alert_edge_triggered = setup->alert_edge_triggered;
|
|
|
- alert->irq = setup->irq;
|
|
|
- INIT_WORK(&alert->alert, smbus_alert);
|
|
|
+ irq = setup->irq;
|
|
|
+ INIT_WORK(&alert->alert, smbalert_work);
|
|
|
alert->ara = ara;
|
|
|
|
|
|
- if (setup->irq > 0) {
|
|
|
- res = devm_request_irq(&ara->dev, setup->irq, smbalert_irq,
|
|
|
- 0, "smbus_alert", alert);
|
|
|
+ if (irq > 0) {
|
|
|
+ res = devm_request_threaded_irq(&ara->dev, irq,
|
|
|
+ NULL, smbus_alert,
|
|
|
+ IRQF_SHARED | IRQF_ONESHOT,
|
|
|
+ "smbus_alert", alert);
|
|
|
if (res)
|
|
|
return res;
|
|
|
}
|
|
|
|
|
|
i2c_set_clientdata(ara, alert);
|
|
|
- dev_info(&adapter->dev, "supports SMBALERT#, %s trigger\n",
|
|
|
- setup->alert_edge_triggered ? "edge" : "level");
|
|
|
+ dev_info(&adapter->dev, "supports SMBALERT#\n");
|
|
|
|
|
|
return 0;
|
|
|
}
|