mirror of https://gitee.com/openkylin/linux.git
[media] adv7180: Use threaded IRQ instead of IRQ + workqueue
The proper way to handle IRQs that need to be able to sleep in their IRQ handler is to use a threaded IRQ. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
This commit is contained in:
parent
7933c177fa
commit
0c25534d45
|
@ -123,7 +123,6 @@
|
||||||
struct adv7180_state {
|
struct adv7180_state {
|
||||||
struct v4l2_ctrl_handler ctrl_hdl;
|
struct v4l2_ctrl_handler ctrl_hdl;
|
||||||
struct v4l2_subdev sd;
|
struct v4l2_subdev sd;
|
||||||
struct work_struct work;
|
|
||||||
struct mutex mutex; /* mutual excl. when accessing chip */
|
struct mutex mutex; /* mutual excl. when accessing chip */
|
||||||
int irq;
|
int irq;
|
||||||
v4l2_std_id curr_norm;
|
v4l2_std_id curr_norm;
|
||||||
|
@ -449,10 +448,9 @@ static const struct v4l2_subdev_ops adv7180_ops = {
|
||||||
.video = &adv7180_video_ops,
|
.video = &adv7180_video_ops,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void adv7180_work(struct work_struct *work)
|
static irqreturn_t adv7180_irq(int irq, void *devid)
|
||||||
{
|
{
|
||||||
struct adv7180_state *state = container_of(work, struct adv7180_state,
|
struct adv7180_state *state = devid;
|
||||||
work);
|
|
||||||
struct i2c_client *client = v4l2_get_subdevdata(&state->sd);
|
struct i2c_client *client = v4l2_get_subdevdata(&state->sd);
|
||||||
u8 isr3;
|
u8 isr3;
|
||||||
|
|
||||||
|
@ -468,17 +466,6 @@ static void adv7180_work(struct work_struct *work)
|
||||||
__adv7180_status(client, NULL, &state->curr_norm);
|
__adv7180_status(client, NULL, &state->curr_norm);
|
||||||
mutex_unlock(&state->mutex);
|
mutex_unlock(&state->mutex);
|
||||||
|
|
||||||
enable_irq(state->irq);
|
|
||||||
}
|
|
||||||
|
|
||||||
static irqreturn_t adv7180_irq(int irq, void *devid)
|
|
||||||
{
|
|
||||||
struct adv7180_state *state = devid;
|
|
||||||
|
|
||||||
schedule_work(&state->work);
|
|
||||||
|
|
||||||
disable_irq_nosync(state->irq);
|
|
||||||
|
|
||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -533,8 +520,8 @@ static int init_device(struct i2c_client *client, struct adv7180_state *state)
|
||||||
|
|
||||||
/* register for interrupts */
|
/* register for interrupts */
|
||||||
if (state->irq > 0) {
|
if (state->irq > 0) {
|
||||||
ret = request_irq(state->irq, adv7180_irq, 0, KBUILD_MODNAME,
|
ret = request_threaded_irq(state->irq, NULL, adv7180_irq,
|
||||||
state);
|
IRQF_ONESHOT, KBUILD_MODNAME, state);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
@ -598,7 +585,6 @@ static int adv7180_probe(struct i2c_client *client,
|
||||||
}
|
}
|
||||||
|
|
||||||
state->irq = client->irq;
|
state->irq = client->irq;
|
||||||
INIT_WORK(&state->work, adv7180_work);
|
|
||||||
mutex_init(&state->mutex);
|
mutex_init(&state->mutex);
|
||||||
state->autodetect = true;
|
state->autodetect = true;
|
||||||
state->input = 0;
|
state->input = 0;
|
||||||
|
@ -626,17 +612,8 @@ static int adv7180_remove(struct i2c_client *client)
|
||||||
struct v4l2_subdev *sd = i2c_get_clientdata(client);
|
struct v4l2_subdev *sd = i2c_get_clientdata(client);
|
||||||
struct adv7180_state *state = to_state(sd);
|
struct adv7180_state *state = to_state(sd);
|
||||||
|
|
||||||
if (state->irq > 0) {
|
if (state->irq > 0)
|
||||||
free_irq(client->irq, state);
|
free_irq(client->irq, state);
|
||||||
if (cancel_work_sync(&state->work)) {
|
|
||||||
/*
|
|
||||||
* Work was pending, therefore we need to enable
|
|
||||||
* IRQ here to balance the disable_irq() done in the
|
|
||||||
* interrupt handler.
|
|
||||||
*/
|
|
||||||
enable_irq(state->irq);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
v4l2_device_unregister_subdev(sd);
|
v4l2_device_unregister_subdev(sd);
|
||||||
adv7180_exit_controls(state);
|
adv7180_exit_controls(state);
|
||||||
|
|
Loading…
Reference in New Issue