media video cx23888 driver: ported to new kfifo API
Fix the cx23888 driver to use the new kfifo API. Using kfifo_reset() may result in a possible race conditions. This patch fixes it by using a spinlock around the kfifo_reset() function. Signed-off-by: Stefani Seibold <stefani@seibold.net> Cc: Mauro Carvalho Chehab <mchehab@infradead.org> Reviewed-by: Andy Walls <awalls@radix.net> Acked-by: Andy Walls <awalls@radix.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
Родитель
86d4880313
Коммит
7801edb0b8
|
@ -124,15 +124,12 @@ struct cx23888_ir_state {
|
|||
atomic_t rxclk_divider;
|
||||
atomic_t rx_invert;
|
||||
|
||||
struct kfifo *rx_kfifo;
|
||||
struct kfifo rx_kfifo;
|
||||
spinlock_t rx_kfifo_lock;
|
||||
|
||||
struct v4l2_subdev_ir_parameters tx_params;
|
||||
struct mutex tx_params_lock;
|
||||
atomic_t txclk_divider;
|
||||
|
||||
struct kfifo *tx_kfifo;
|
||||
spinlock_t tx_kfifo_lock;
|
||||
};
|
||||
|
||||
static inline struct cx23888_ir_state *to_state(struct v4l2_subdev *sd)
|
||||
|
@ -522,6 +519,7 @@ static int cx23888_ir_irq_handler(struct v4l2_subdev *sd, u32 status,
|
|||
{
|
||||
struct cx23888_ir_state *state = to_state(sd);
|
||||
struct cx23885_dev *dev = state->dev;
|
||||
unsigned long flags;
|
||||
|
||||
u32 cntrl = cx23888_ir_read4(dev, CX23888_IR_CNTRL_REG);
|
||||
u32 irqen = cx23888_ir_read4(dev, CX23888_IR_IRQEN_REG);
|
||||
|
@ -594,8 +592,9 @@ static int cx23888_ir_irq_handler(struct v4l2_subdev *sd, u32 status,
|
|||
if (i == 0)
|
||||
break;
|
||||
j = i * sizeof(u32);
|
||||
k = kfifo_put(state->rx_kfifo,
|
||||
(unsigned char *) rx_data, j);
|
||||
k = kfifo_in_locked(&state->rx_kfifo,
|
||||
(unsigned char *) rx_data, j,
|
||||
&state->rx_kfifo_lock);
|
||||
if (k != j)
|
||||
kror++; /* rx_kfifo over run */
|
||||
}
|
||||
|
@ -631,8 +630,11 @@ static int cx23888_ir_irq_handler(struct v4l2_subdev *sd, u32 status,
|
|||
cx23888_ir_write4(dev, CX23888_IR_CNTRL_REG, cntrl);
|
||||
*handled = true;
|
||||
}
|
||||
if (kfifo_len(state->rx_kfifo) >= CX23888_IR_RX_KFIFO_SIZE / 2)
|
||||
|
||||
spin_lock_irqsave(&state->rx_kfifo_lock, flags);
|
||||
if (kfifo_len(&state->rx_kfifo) >= CX23888_IR_RX_KFIFO_SIZE / 2)
|
||||
events |= V4L2_SUBDEV_IR_RX_FIFO_SERVICE_REQ;
|
||||
spin_unlock_irqrestore(&state->rx_kfifo_lock, flags);
|
||||
|
||||
if (events)
|
||||
v4l2_subdev_notify(sd, V4L2_SUBDEV_IR_RX_NOTIFY, &events);
|
||||
|
@ -657,7 +659,7 @@ static int cx23888_ir_rx_read(struct v4l2_subdev *sd, u8 *buf, size_t count,
|
|||
return 0;
|
||||
}
|
||||
|
||||
n = kfifo_get(state->rx_kfifo, buf, n);
|
||||
n = kfifo_out_locked(&state->rx_kfifo, buf, n, &state->rx_kfifo_lock);
|
||||
|
||||
n /= sizeof(u32);
|
||||
*num = n * sizeof(u32);
|
||||
|
@ -785,7 +787,12 @@ static int cx23888_ir_rx_s_parameters(struct v4l2_subdev *sd,
|
|||
o->interrupt_enable = p->interrupt_enable;
|
||||
o->enable = p->enable;
|
||||
if (p->enable) {
|
||||
kfifo_reset(state->rx_kfifo);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&state->rx_kfifo_lock, flags);
|
||||
kfifo_reset(&state->rx_kfifo);
|
||||
/* reset tx_fifo too if there is one... */
|
||||
spin_unlock_irqrestore(&state->rx_kfifo_lock, flags);
|
||||
if (p->interrupt_enable)
|
||||
irqenable_rx(dev, IRQEN_RSE | IRQEN_RTE | IRQEN_ROE);
|
||||
control_rx_enable(dev, p->enable);
|
||||
|
@ -892,7 +899,6 @@ static int cx23888_ir_tx_s_parameters(struct v4l2_subdev *sd,
|
|||
o->interrupt_enable = p->interrupt_enable;
|
||||
o->enable = p->enable;
|
||||
if (p->enable) {
|
||||
kfifo_reset(state->tx_kfifo);
|
||||
if (p->interrupt_enable)
|
||||
irqenable_tx(dev, IRQEN_TSE);
|
||||
control_tx_enable(dev, p->enable);
|
||||
|
@ -1168,19 +1174,9 @@ int cx23888_ir_probe(struct cx23885_dev *dev)
|
|||
return -ENOMEM;
|
||||
|
||||
spin_lock_init(&state->rx_kfifo_lock);
|
||||
state->rx_kfifo = kfifo_alloc(CX23888_IR_RX_KFIFO_SIZE, GFP_KERNEL,
|
||||
&state->rx_kfifo_lock);
|
||||
if (state->rx_kfifo == NULL)
|
||||
if (kfifo_alloc(&state->rx_kfifo, CX23888_IR_RX_KFIFO_SIZE, GFP_KERNEL))
|
||||
return -ENOMEM;
|
||||
|
||||
spin_lock_init(&state->tx_kfifo_lock);
|
||||
state->tx_kfifo = kfifo_alloc(CX23888_IR_TX_KFIFO_SIZE, GFP_KERNEL,
|
||||
&state->tx_kfifo_lock);
|
||||
if (state->tx_kfifo == NULL) {
|
||||
kfifo_free(state->rx_kfifo);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
state->dev = dev;
|
||||
state->id = V4L2_IDENT_CX23888_IR;
|
||||
state->rev = 0;
|
||||
|
@ -1211,8 +1207,7 @@ int cx23888_ir_probe(struct cx23885_dev *dev)
|
|||
sizeof(struct v4l2_subdev_ir_parameters));
|
||||
v4l2_subdev_call(sd, ir, tx_s_parameters, &default_params);
|
||||
} else {
|
||||
kfifo_free(state->rx_kfifo);
|
||||
kfifo_free(state->tx_kfifo);
|
||||
kfifo_free(&state->rx_kfifo);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -1231,8 +1226,7 @@ int cx23888_ir_remove(struct cx23885_dev *dev)
|
|||
|
||||
state = to_state(sd);
|
||||
v4l2_device_unregister_subdev(sd);
|
||||
kfifo_free(state->rx_kfifo);
|
||||
kfifo_free(state->tx_kfifo);
|
||||
kfifo_free(&state->rx_kfifo);
|
||||
kfree(state);
|
||||
/* Nothing more to free() as state held the actual v4l2_subdev object */
|
||||
return 0;
|
||||
|
|
Загрузка…
Ссылка в новой задаче