diff options
| -rw-r--r-- | drivers/media/video/cx23885/cx23888-ir.c | 44 |
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 | ||
| 138 | static inline struct cx23888_ir_state *to_state(struct v4l2_subdev *sd) | 135 | 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, | |||
| 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; |
