aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/cx23885/cx23888-ir.c
diff options
context:
space:
mode:
authorStefani Seibold <stefani@seibold.net>2009-12-21 17:37:33 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2009-12-22 17:17:57 -0500
commit7801edb0b8b66e83c13623b483bc2e846c007c9d (patch)
treee536d39689ca4e25145aeeb84abf7335162c34c8 /drivers/media/video/cx23885/cx23888-ir.c
parent86d4880313603810901f639ccb5c88ff13d4ad3c (diff)
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>
Diffstat (limited to 'drivers/media/video/cx23885/cx23888-ir.c')
-rw-r--r--drivers/media/video/cx23885/cx23888-ir.c44
1 files changed, 19 insertions, 25 deletions
diff --git a/drivers/media/video/cx23885/cx23888-ir.c b/drivers/media/video/cx23885/cx23888-ir.c
index 3ccc8afeccf3..2bf57a4527d3 100644
--- a/drivers/media/video/cx23885/cx23888-ir.c
+++ b/drivers/media/video/cx23885/cx23888-ir.c
@@ -124,15 +124,12 @@ struct cx23888_ir_state {
124 atomic_t rxclk_divider; 124 atomic_t rxclk_divider;
125 atomic_t rx_invert; 125 atomic_t rx_invert;
126 126
127 struct kfifo *rx_kfifo; 127 struct kfifo rx_kfifo;
128 spinlock_t rx_kfifo_lock; 128 spinlock_t rx_kfifo_lock;
129 129
130 struct v4l2_subdev_ir_parameters tx_params; 130 struct v4l2_subdev_ir_parameters tx_params;
131 struct mutex tx_params_lock; 131 struct mutex tx_params_lock;
132 atomic_t txclk_divider; 132 atomic_t txclk_divider;
133
134 struct kfifo *tx_kfifo;
135 spinlock_t tx_kfifo_lock;
136}; 133};
137 134
138static inline struct cx23888_ir_state *to_state(struct v4l2_subdev *sd) 135static 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,
522{ 519{
523 struct cx23888_ir_state *state = to_state(sd); 520 struct cx23888_ir_state *state = to_state(sd);
524 struct cx23885_dev *dev = state->dev; 521 struct cx23885_dev *dev = state->dev;
522 unsigned long flags;
525 523
526 u32 cntrl = cx23888_ir_read4(dev, CX23888_IR_CNTRL_REG); 524 u32 cntrl = cx23888_ir_read4(dev, CX23888_IR_CNTRL_REG);
527 u32 irqen = cx23888_ir_read4(dev, CX23888_IR_IRQEN_REG); 525 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,
594 if (i == 0) 592 if (i == 0)
595 break; 593 break;
596 j = i * sizeof(u32); 594 j = i * sizeof(u32);
597 k = kfifo_put(state->rx_kfifo, 595 k = kfifo_in_locked(&state->rx_kfifo,
598 (unsigned char *) rx_data, j); 596 (unsigned char *) rx_data, j,
597 &state->rx_kfifo_lock);
599 if (k != j) 598 if (k != j)
600 kror++; /* rx_kfifo over run */ 599 kror++; /* rx_kfifo over run */
601 } 600 }
@@ -631,8 +630,11 @@ static int cx23888_ir_irq_handler(struct v4l2_subdev *sd, u32 status,
631 cx23888_ir_write4(dev, CX23888_IR_CNTRL_REG, cntrl); 630 cx23888_ir_write4(dev, CX23888_IR_CNTRL_REG, cntrl);
632 *handled = true; 631 *handled = true;
633 } 632 }
634 if (kfifo_len(state->rx_kfifo) >= CX23888_IR_RX_KFIFO_SIZE / 2) 633
634 spin_lock_irqsave(&state->rx_kfifo_lock, flags);
635 if (kfifo_len(&state->rx_kfifo) >= CX23888_IR_RX_KFIFO_SIZE / 2)
635 events |= V4L2_SUBDEV_IR_RX_FIFO_SERVICE_REQ; 636 events |= V4L2_SUBDEV_IR_RX_FIFO_SERVICE_REQ;
637 spin_unlock_irqrestore(&state->rx_kfifo_lock, flags);
636 638
637 if (events) 639 if (events)
638 v4l2_subdev_notify(sd, V4L2_SUBDEV_IR_RX_NOTIFY, &events); 640 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,
657 return 0; 659 return 0;
658 } 660 }
659 661
660 n = kfifo_get(state->rx_kfifo, buf, n); 662 n = kfifo_out_locked(&state->rx_kfifo, buf, n, &state->rx_kfifo_lock);
661 663
662 n /= sizeof(u32); 664 n /= sizeof(u32);
663 *num = n * sizeof(u32); 665 *num = n * sizeof(u32);
@@ -785,7 +787,12 @@ static int cx23888_ir_rx_s_parameters(struct v4l2_subdev *sd,
785 o->interrupt_enable = p->interrupt_enable; 787 o->interrupt_enable = p->interrupt_enable;
786 o->enable = p->enable; 788 o->enable = p->enable;
787 if (p->enable) { 789 if (p->enable) {
788 kfifo_reset(state->rx_kfifo); 790 unsigned long flags;
791
792 spin_lock_irqsave(&state->rx_kfifo_lock, flags);
793 kfifo_reset(&state->rx_kfifo);
794 /* reset tx_fifo too if there is one... */
795 spin_unlock_irqrestore(&state->rx_kfifo_lock, flags);
789 if (p->interrupt_enable) 796 if (p->interrupt_enable)
790 irqenable_rx(dev, IRQEN_RSE | IRQEN_RTE | IRQEN_ROE); 797 irqenable_rx(dev, IRQEN_RSE | IRQEN_RTE | IRQEN_ROE);
791 control_rx_enable(dev, p->enable); 798 control_rx_enable(dev, p->enable);
@@ -892,7 +899,6 @@ static int cx23888_ir_tx_s_parameters(struct v4l2_subdev *sd,
892 o->interrupt_enable = p->interrupt_enable; 899 o->interrupt_enable = p->interrupt_enable;
893 o->enable = p->enable; 900 o->enable = p->enable;
894 if (p->enable) { 901 if (p->enable) {
895 kfifo_reset(state->tx_kfifo);
896 if (p->interrupt_enable) 902 if (p->interrupt_enable)
897 irqenable_tx(dev, IRQEN_TSE); 903 irqenable_tx(dev, IRQEN_TSE);
898 control_tx_enable(dev, p->enable); 904 control_tx_enable(dev, p->enable);
@@ -1168,18 +1174,8 @@ int cx23888_ir_probe(struct cx23885_dev *dev)
1168 return -ENOMEM; 1174 return -ENOMEM;
1169 1175
1170 spin_lock_init(&state->rx_kfifo_lock); 1176 spin_lock_init(&state->rx_kfifo_lock);
1171 state->rx_kfifo = kfifo_alloc(CX23888_IR_RX_KFIFO_SIZE, GFP_KERNEL, 1177 if (kfifo_alloc(&state->rx_kfifo, CX23888_IR_RX_KFIFO_SIZE, GFP_KERNEL))
1172 &state->rx_kfifo_lock);
1173 if (state->rx_kfifo == NULL)
1174 return -ENOMEM;
1175
1176 spin_lock_init(&state->tx_kfifo_lock);
1177 state->tx_kfifo = kfifo_alloc(CX23888_IR_TX_KFIFO_SIZE, GFP_KERNEL,
1178 &state->tx_kfifo_lock);
1179 if (state->tx_kfifo == NULL) {
1180 kfifo_free(state->rx_kfifo);
1181 return -ENOMEM; 1178 return -ENOMEM;
1182 }
1183 1179
1184 state->dev = dev; 1180 state->dev = dev;
1185 state->id = V4L2_IDENT_CX23888_IR; 1181 state->id = V4L2_IDENT_CX23888_IR;
@@ -1211,8 +1207,7 @@ int cx23888_ir_probe(struct cx23885_dev *dev)
1211 sizeof(struct v4l2_subdev_ir_parameters)); 1207 sizeof(struct v4l2_subdev_ir_parameters));
1212 v4l2_subdev_call(sd, ir, tx_s_parameters, &default_params); 1208 v4l2_subdev_call(sd, ir, tx_s_parameters, &default_params);
1213 } else { 1209 } else {
1214 kfifo_free(state->rx_kfifo); 1210 kfifo_free(&state->rx_kfifo);
1215 kfifo_free(state->tx_kfifo);
1216 } 1211 }
1217 return ret; 1212 return ret;
1218} 1213}
@@ -1231,8 +1226,7 @@ int cx23888_ir_remove(struct cx23885_dev *dev)
1231 1226
1232 state = to_state(sd); 1227 state = to_state(sd);
1233 v4l2_device_unregister_subdev(sd); 1228 v4l2_device_unregister_subdev(sd);
1234 kfifo_free(state->rx_kfifo); 1229 kfifo_free(&state->rx_kfifo);
1235 kfifo_free(state->tx_kfifo);
1236 kfree(state); 1230 kfree(state);
1237 /* Nothing more to free() as state held the actual v4l2_subdev object */ 1231 /* Nothing more to free() as state held the actual v4l2_subdev object */
1238 return 0; 1232 return 0;