aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorSean Young <sean@mess.org>2012-09-28 03:44:29 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-10-07 08:03:35 -0400
commit48b0fa6afa7ee6a274e060564d2389ffea413762 (patch)
tree9fdedae472772dc35f34f5b3c42239d8fdef2f7d /drivers/media
parent947c48086623d9ca2207dd0434bd58458af4ba86 (diff)
[media] iguanair: cannot send data from the stack
Note that the firmware already disables the receiver before transmit, there is no need to do this from the driver. Reported-by: Fengguang Wu <fengguang.wu@intel.com> Signed-off-by: Sean Young <sean@mess.org> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/rc/iguanair.c147
1 files changed, 75 insertions, 72 deletions
diff --git a/drivers/media/rc/iguanair.c b/drivers/media/rc/iguanair.c
index 1e4c68a5cecf..51d7057aca04 100644
--- a/drivers/media/rc/iguanair.c
+++ b/drivers/media/rc/iguanair.c
@@ -28,6 +28,7 @@
28#include <media/rc-core.h> 28#include <media/rc-core.h>
29 29
30#define DRIVER_NAME "iguanair" 30#define DRIVER_NAME "iguanair"
31#define BUF_SIZE 152
31 32
32struct iguanair { 33struct iguanair {
33 struct rc_dev *rc; 34 struct rc_dev *rc;
@@ -35,26 +36,23 @@ struct iguanair {
35 struct device *dev; 36 struct device *dev;
36 struct usb_device *udev; 37 struct usb_device *udev;
37 38
38 int pipe_out;
39 uint16_t version; 39 uint16_t version;
40 uint8_t bufsize; 40 uint8_t bufsize;
41 uint8_t cycle_overhead;
41 42
42 struct mutex lock; 43 struct mutex lock;
43 44
44 /* receiver support */ 45 /* receiver support */
45 bool receiver_on; 46 bool receiver_on;
46 dma_addr_t dma_in; 47 dma_addr_t dma_in, dma_out;
47 uint8_t *buf_in; 48 uint8_t *buf_in;
48 struct urb *urb_in; 49 struct urb *urb_in, *urb_out;
49 struct completion completion; 50 struct completion completion;
50 51
51 /* transmit support */ 52 /* transmit support */
52 bool tx_overflow; 53 bool tx_overflow;
53 uint32_t carrier; 54 uint32_t carrier;
54 uint8_t cycle_overhead; 55 struct send_packet *packet;
55 uint8_t channels;
56 uint8_t busy4;
57 uint8_t busy7;
58 56
59 char name[64]; 57 char name[64];
60 char phys[64]; 58 char phys[64];
@@ -73,7 +71,8 @@ struct iguanair {
73#define DIR_IN 0xdc 71#define DIR_IN 0xdc
74#define DIR_OUT 0xcd 72#define DIR_OUT 0xcd
75 73
76#define MAX_PACKET_SIZE 8u 74#define MAX_IN_PACKET 8u
75#define MAX_OUT_PACKET (sizeof(struct send_packet) + BUF_SIZE)
77#define TIMEOUT 1000 76#define TIMEOUT 1000
78#define RX_RESOLUTION 21333 77#define RX_RESOLUTION 21333
79 78
@@ -191,20 +190,25 @@ static void iguanair_rx(struct urb *urb)
191 dev_warn(ir->dev, "failed to resubmit urb: %d\n", rc); 190 dev_warn(ir->dev, "failed to resubmit urb: %d\n", rc);
192} 191}
193 192
194static int iguanair_send(struct iguanair *ir, void *data, unsigned size) 193static void iguanair_irq_out(struct urb *urb)
195{ 194{
196 int rc, transferred; 195 struct iguanair *ir = urb->context;
196
197 if (urb->status)
198 dev_dbg(ir->dev, "Error: out urb status = %d\n", urb->status);
199}
200
201static int iguanair_send(struct iguanair *ir, unsigned size)
202{
203 int rc;
197 204
198 INIT_COMPLETION(ir->completion); 205 INIT_COMPLETION(ir->completion);
199 206
200 rc = usb_interrupt_msg(ir->udev, ir->pipe_out, data, size, 207 ir->urb_out->transfer_buffer_length = size;
201 &transferred, TIMEOUT); 208 rc = usb_submit_urb(ir->urb_out, GFP_KERNEL);
202 if (rc) 209 if (rc)
203 return rc; 210 return rc;
204 211
205 if (transferred != size)
206 return -EIO;
207
208 if (wait_for_completion_timeout(&ir->completion, TIMEOUT) == 0) 212 if (wait_for_completion_timeout(&ir->completion, TIMEOUT) == 0)
209 return -ETIMEDOUT; 213 return -ETIMEDOUT;
210 214
@@ -213,14 +217,13 @@ static int iguanair_send(struct iguanair *ir, void *data, unsigned size)
213 217
214static int iguanair_get_features(struct iguanair *ir) 218static int iguanair_get_features(struct iguanair *ir)
215{ 219{
216 struct packet packet;
217 int rc; 220 int rc;
218 221
219 packet.start = 0; 222 ir->packet->header.start = 0;
220 packet.direction = DIR_OUT; 223 ir->packet->header.direction = DIR_OUT;
221 packet.cmd = CMD_GET_VERSION; 224 ir->packet->header.cmd = CMD_GET_VERSION;
222 225
223 rc = iguanair_send(ir, &packet, sizeof(packet)); 226 rc = iguanair_send(ir, sizeof(ir->packet->header));
224 if (rc) { 227 if (rc) {
225 dev_info(ir->dev, "failed to get version\n"); 228 dev_info(ir->dev, "failed to get version\n");
226 goto out; 229 goto out;
@@ -235,17 +238,23 @@ static int iguanair_get_features(struct iguanair *ir)
235 ir->bufsize = 150; 238 ir->bufsize = 150;
236 ir->cycle_overhead = 65; 239 ir->cycle_overhead = 65;
237 240
238 packet.cmd = CMD_GET_BUFSIZE; 241 ir->packet->header.cmd = CMD_GET_BUFSIZE;
239 242
240 rc = iguanair_send(ir, &packet, sizeof(packet)); 243 rc = iguanair_send(ir, sizeof(ir->packet->header));
241 if (rc) { 244 if (rc) {
242 dev_info(ir->dev, "failed to get buffer size\n"); 245 dev_info(ir->dev, "failed to get buffer size\n");
243 goto out; 246 goto out;
244 } 247 }
245 248
246 packet.cmd = CMD_GET_FEATURES; 249 if (ir->bufsize > BUF_SIZE) {
250 dev_info(ir->dev, "buffer size %u larger than expected\n",
251 ir->bufsize);
252 ir->bufsize = BUF_SIZE;
253 }
254
255 ir->packet->header.cmd = CMD_GET_FEATURES;
247 256
248 rc = iguanair_send(ir, &packet, sizeof(packet)); 257 rc = iguanair_send(ir, sizeof(ir->packet->header));
249 if (rc) { 258 if (rc) {
250 dev_info(ir->dev, "failed to get features\n"); 259 dev_info(ir->dev, "failed to get features\n");
251 goto out; 260 goto out;
@@ -257,13 +266,18 @@ out:
257 266
258static int iguanair_receiver(struct iguanair *ir, bool enable) 267static int iguanair_receiver(struct iguanair *ir, bool enable)
259{ 268{
260 struct packet packet = { 0, DIR_OUT, enable ? 269 int rc;
261 CMD_RECEIVER_ON : CMD_RECEIVER_OFF }; 270
271 ir->packet->header.start = 0;
272 ir->packet->header.direction = DIR_OUT;
273 ir->packet->header.cmd = enable ? CMD_RECEIVER_ON : CMD_RECEIVER_OFF;
262 274
263 if (enable) 275 if (enable)
264 ir_raw_event_reset(ir->rc); 276 ir_raw_event_reset(ir->rc);
265 277
266 return iguanair_send(ir, &packet, sizeof(packet)); 278 rc = iguanair_send(ir, sizeof(ir->packet->header));
279
280 return rc;
267} 281}
268 282
269/* 283/*
@@ -308,8 +322,8 @@ static int iguanair_set_tx_carrier(struct rc_dev *dev, uint32_t carrier)
308 fours = (cycles - sevens * 7) / 4; 322 fours = (cycles - sevens * 7) / 4;
309 323
310 /* magic happens here */ 324 /* magic happens here */
311 ir->busy7 = (4 - sevens) * 2; 325 ir->packet->busy7 = (4 - sevens) * 2;
312 ir->busy4 = 110 - fours; 326 ir->packet->busy4 = 110 - fours;
313 } 327 }
314 328
315 mutex_unlock(&ir->lock); 329 mutex_unlock(&ir->lock);
@@ -325,7 +339,7 @@ static int iguanair_set_tx_mask(struct rc_dev *dev, uint32_t mask)
325 return 4; 339 return 4;
326 340
327 mutex_lock(&ir->lock); 341 mutex_lock(&ir->lock);
328 ir->channels = mask; 342 ir->packet->channels = mask << 4;
329 mutex_unlock(&ir->lock); 343 mutex_unlock(&ir->lock);
330 344
331 return 0; 345 return 0;
@@ -337,16 +351,9 @@ static int iguanair_tx(struct rc_dev *dev, unsigned *txbuf, unsigned count)
337 uint8_t space; 351 uint8_t space;
338 unsigned i, size, periods, bytes; 352 unsigned i, size, periods, bytes;
339 int rc; 353 int rc;
340 struct send_packet *packet;
341 354
342 mutex_lock(&ir->lock); 355 mutex_lock(&ir->lock);
343 356
344 packet = kmalloc(sizeof(*packet) + ir->bufsize, GFP_KERNEL);
345 if (!packet) {
346 rc = -ENOMEM;
347 goto out;
348 }
349
350 /* convert from us to carrier periods */ 357 /* convert from us to carrier periods */
351 for (i = space = size = 0; i < count; i++) { 358 for (i = space = size = 0; i < count; i++) {
352 periods = DIV_ROUND_CLOSEST(txbuf[i] * ir->carrier, 1000000); 359 periods = DIV_ROUND_CLOSEST(txbuf[i] * ir->carrier, 1000000);
@@ -356,11 +363,11 @@ static int iguanair_tx(struct rc_dev *dev, unsigned *txbuf, unsigned count)
356 break; 363 break;
357 } 364 }
358 while (periods > 127) { 365 while (periods > 127) {
359 packet->payload[size++] = 127 | space; 366 ir->packet->payload[size++] = 127 | space;
360 periods -= 127; 367 periods -= 127;
361 } 368 }
362 369
363 packet->payload[size++] = periods | space; 370 ir->packet->payload[size++] = periods | space;
364 space ^= 0x80; 371 space ^= 0x80;
365 } 372 }
366 373
@@ -369,36 +376,19 @@ static int iguanair_tx(struct rc_dev *dev, unsigned *txbuf, unsigned count)
369 goto out; 376 goto out;
370 } 377 }
371 378
372 packet->header.start = 0; 379 ir->packet->header.start = 0;
373 packet->header.direction = DIR_OUT; 380 ir->packet->header.direction = DIR_OUT;
374 packet->header.cmd = CMD_SEND; 381 ir->packet->header.cmd = CMD_SEND;
375 packet->length = size; 382 ir->packet->length = size;
376 packet->channels = ir->channels << 4;
377 packet->busy7 = ir->busy7;
378 packet->busy4 = ir->busy4;
379
380 if (ir->receiver_on) {
381 rc = iguanair_receiver(ir, false);
382 if (rc) {
383 dev_warn(ir->dev, "disable receiver before transmit failed\n");
384 goto out;
385 }
386 }
387 383
388 ir->tx_overflow = false; 384 ir->tx_overflow = false;
389 385
390 rc = iguanair_send(ir, packet, size + 8); 386 rc = iguanair_send(ir, sizeof(*ir->packet) + size);
391 387
392 if (rc == 0 && ir->tx_overflow) 388 if (rc == 0 && ir->tx_overflow)
393 rc = -EOVERFLOW; 389 rc = -EOVERFLOW;
394 390
395 if (ir->receiver_on) {
396 if (iguanair_receiver(ir, true))
397 dev_warn(ir->dev, "re-enable receiver after transmit failed\n");
398 }
399
400out: 391out:
401 kfree(packet);
402 mutex_unlock(&ir->lock); 392 mutex_unlock(&ir->lock);
403 393
404 return rc ? rc : count; 394 return rc ? rc : count;
@@ -411,8 +401,6 @@ static int iguanair_open(struct rc_dev *rdev)
411 401
412 mutex_lock(&ir->lock); 402 mutex_lock(&ir->lock);
413 403
414 BUG_ON(ir->receiver_on);
415
416 rc = iguanair_receiver(ir, true); 404 rc = iguanair_receiver(ir, true);
417 if (rc == 0) 405 if (rc == 0)
418 ir->receiver_on = true; 406 ir->receiver_on = true;
@@ -443,7 +431,7 @@ static int __devinit iguanair_probe(struct usb_interface *intf,
443 struct usb_device *udev = interface_to_usbdev(intf); 431 struct usb_device *udev = interface_to_usbdev(intf);
444 struct iguanair *ir; 432 struct iguanair *ir;
445 struct rc_dev *rc; 433 struct rc_dev *rc;
446 int ret, pipein; 434 int ret, pipein, pipeout;
447 struct usb_host_interface *idesc; 435 struct usb_host_interface *idesc;
448 436
449 ir = kzalloc(sizeof(*ir), GFP_KERNEL); 437 ir = kzalloc(sizeof(*ir), GFP_KERNEL);
@@ -453,11 +441,14 @@ static int __devinit iguanair_probe(struct usb_interface *intf,
453 goto out; 441 goto out;
454 } 442 }
455 443
456 ir->buf_in = usb_alloc_coherent(udev, MAX_PACKET_SIZE, GFP_KERNEL, 444 ir->buf_in = usb_alloc_coherent(udev, MAX_IN_PACKET, GFP_KERNEL,
457 &ir->dma_in); 445 &ir->dma_in);
446 ir->packet = usb_alloc_coherent(udev, MAX_OUT_PACKET, GFP_KERNEL,
447 &ir->dma_out);
458 ir->urb_in = usb_alloc_urb(0, GFP_KERNEL); 448 ir->urb_in = usb_alloc_urb(0, GFP_KERNEL);
449 ir->urb_out = usb_alloc_urb(0, GFP_KERNEL);
459 450
460 if (!ir->buf_in || !ir->urb_in) { 451 if (!ir->buf_in || !ir->packet || !ir->urb_in || !ir->urb_out) {
461 ret = -ENOMEM; 452 ret = -ENOMEM;
462 goto out; 453 goto out;
463 } 454 }
@@ -472,13 +463,18 @@ static int __devinit iguanair_probe(struct usb_interface *intf,
472 ir->rc = rc; 463 ir->rc = rc;
473 ir->dev = &intf->dev; 464 ir->dev = &intf->dev;
474 ir->udev = udev; 465 ir->udev = udev;
475 ir->pipe_out = usb_sndintpipe(udev,
476 idesc->endpoint[1].desc.bEndpointAddress);
477 mutex_init(&ir->lock); 466 mutex_init(&ir->lock);
467
478 init_completion(&ir->completion); 468 init_completion(&ir->completion);
469 pipeout = usb_sndintpipe(udev,
470 idesc->endpoint[1].desc.bEndpointAddress);
471 usb_fill_int_urb(ir->urb_out, udev, pipeout, ir->packet, MAX_OUT_PACKET,
472 iguanair_irq_out, ir, 1);
473 ir->urb_out->transfer_dma = ir->dma_out;
474 ir->urb_out->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
479 475
480 pipein = usb_rcvintpipe(udev, idesc->endpoint[0].desc.bEndpointAddress); 476 pipein = usb_rcvintpipe(udev, idesc->endpoint[0].desc.bEndpointAddress);
481 usb_fill_int_urb(ir->urb_in, udev, pipein, ir->buf_in, MAX_PACKET_SIZE, 477 usb_fill_int_urb(ir->urb_in, udev, pipein, ir->buf_in, MAX_IN_PACKET,
482 iguanair_rx, ir, 1); 478 iguanair_rx, ir, 1);
483 ir->urb_in->transfer_dma = ir->dma_in; 479 ir->urb_in->transfer_dma = ir->dma_in;
484 ir->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; 480 ir->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
@@ -528,11 +524,14 @@ static int __devinit iguanair_probe(struct usb_interface *intf,
528 return 0; 524 return 0;
529out2: 525out2:
530 usb_kill_urb(ir->urb_in); 526 usb_kill_urb(ir->urb_in);
527 usb_kill_urb(ir->urb_out);
531out: 528out:
532 if (ir) { 529 if (ir) {
533 usb_free_urb(ir->urb_in); 530 usb_free_urb(ir->urb_in);
534 usb_free_coherent(udev, MAX_PACKET_SIZE, ir->buf_in, 531 usb_free_urb(ir->urb_out);
535 ir->dma_in); 532 usb_free_coherent(udev, MAX_IN_PACKET, ir->buf_in, ir->dma_in);
533 usb_free_coherent(udev, MAX_OUT_PACKET, ir->packet,
534 ir->dma_out);
536 } 535 }
537 rc_free_device(rc); 536 rc_free_device(rc);
538 kfree(ir); 537 kfree(ir);
@@ -546,8 +545,11 @@ static void __devexit iguanair_disconnect(struct usb_interface *intf)
546 rc_unregister_device(ir->rc); 545 rc_unregister_device(ir->rc);
547 usb_set_intfdata(intf, NULL); 546 usb_set_intfdata(intf, NULL);
548 usb_kill_urb(ir->urb_in); 547 usb_kill_urb(ir->urb_in);
548 usb_kill_urb(ir->urb_out);
549 usb_free_urb(ir->urb_in); 549 usb_free_urb(ir->urb_in);
550 usb_free_coherent(ir->udev, MAX_PACKET_SIZE, ir->buf_in, ir->dma_in); 550 usb_free_urb(ir->urb_out);
551 usb_free_coherent(ir->udev, MAX_IN_PACKET, ir->buf_in, ir->dma_in);
552 usb_free_coherent(ir->udev, MAX_OUT_PACKET, ir->packet, ir->dma_out);
551 kfree(ir); 553 kfree(ir);
552} 554}
553 555
@@ -565,6 +567,7 @@ static int iguanair_suspend(struct usb_interface *intf, pm_message_t message)
565 } 567 }
566 568
567 usb_kill_urb(ir->urb_in); 569 usb_kill_urb(ir->urb_in);
570 usb_kill_urb(ir->urb_out);
568 571
569 mutex_unlock(&ir->lock); 572 mutex_unlock(&ir->lock);
570 573