aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/radio/radio-mr800.c
diff options
context:
space:
mode:
authorDavid Ellingsworth <david@identd.dyndns.org>2009-09-22 20:22:19 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-12-05 15:40:07 -0500
commit4aebc2893eada9e054a37df8bb342a53f8ca0d2a (patch)
tree74346cee8857ecb5859abc47259cc8254d3e0301 /drivers/media/radio/radio-mr800.c
parent0f017212567793ecedf86f709f43ca40f9b84655 (diff)
V4L/DVB (13060): radio-mr800: implement proper locking
Implement proper locking Signed-off-by: David Ellingsworth <david@identd.dyndns.org> Acked-by: Alexey Klimov <klimov.linux@gmail.com> Signed-off-by: Douglas Schilling Landgraf <dougsland@redhat.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/radio/radio-mr800.c')
-rw-r--r--drivers/media/radio/radio-mr800.c181
1 files changed, 106 insertions, 75 deletions
diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c
index a1239083472d..75c69755a04c 100644
--- a/drivers/media/radio/radio-mr800.c
+++ b/drivers/media/radio/radio-mr800.c
@@ -168,11 +168,7 @@ static int amradio_set_mute(struct amradio_device *radio, char argument)
168 int retval; 168 int retval;
169 int size; 169 int size;
170 170
171 /* safety check */ 171 BUG_ON(!mutex_is_locked(&radio->lock));
172 if (radio->removed)
173 return -EIO;
174
175 mutex_lock(&radio->lock);
176 172
177 radio->buffer[0] = 0x00; 173 radio->buffer[0] = 0x00;
178 radio->buffer[1] = 0x55; 174 radio->buffer[1] = 0x55;
@@ -186,15 +182,11 @@ static int amradio_set_mute(struct amradio_device *radio, char argument)
186 retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2), 182 retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2),
187 (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT); 183 (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT);
188 184
189 if (retval < 0 || size != BUFFER_LENGTH) { 185 if (retval < 0 || size != BUFFER_LENGTH)
190 mutex_unlock(&radio->lock);
191 return retval; 186 return retval;
192 }
193 187
194 radio->muted = argument; 188 radio->muted = argument;
195 189
196 mutex_unlock(&radio->lock);
197
198 return retval; 190 return retval;
199} 191}
200 192
@@ -205,11 +197,7 @@ static int amradio_setfreq(struct amradio_device *radio, int freq)
205 int size; 197 int size;
206 unsigned short freq_send = 0x10 + (freq >> 3) / 25; 198 unsigned short freq_send = 0x10 + (freq >> 3) / 25;
207 199
208 /* safety check */ 200 BUG_ON(!mutex_is_locked(&radio->lock));
209 if (radio->removed)
210 return -EIO;
211
212 mutex_lock(&radio->lock);
213 201
214 radio->buffer[0] = 0x00; 202 radio->buffer[0] = 0x00;
215 radio->buffer[1] = 0x55; 203 radio->buffer[1] = 0x55;
@@ -223,10 +211,8 @@ static int amradio_setfreq(struct amradio_device *radio, int freq)
223 retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2), 211 retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2),
224 (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT); 212 (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT);
225 213
226 if (retval < 0 || size != BUFFER_LENGTH) { 214 if (retval < 0 || size != BUFFER_LENGTH)
227 mutex_unlock(&radio->lock);
228 return retval; 215 return retval;
229 }
230 216
231 /* frequency is calculated from freq_send and placed in first 2 bytes */ 217 /* frequency is calculated from freq_send and placed in first 2 bytes */
232 radio->buffer[0] = (freq_send >> 8) & 0xff; 218 radio->buffer[0] = (freq_send >> 8) & 0xff;
@@ -240,13 +226,6 @@ static int amradio_setfreq(struct amradio_device *radio, int freq)
240 retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2), 226 retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2),
241 (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT); 227 (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT);
242 228
243 if (retval < 0 || size != BUFFER_LENGTH) {
244 mutex_unlock(&radio->lock);
245 return retval;
246 }
247
248 mutex_unlock(&radio->lock);
249
250 return retval; 229 return retval;
251} 230}
252 231
@@ -255,11 +234,7 @@ static int amradio_set_stereo(struct amradio_device *radio, char argument)
255 int retval; 234 int retval;
256 int size; 235 int size;
257 236
258 /* safety check */ 237 BUG_ON(!mutex_is_locked(&radio->lock));
259 if (radio->removed)
260 return -EIO;
261
262 mutex_lock(&radio->lock);
263 238
264 radio->buffer[0] = 0x00; 239 radio->buffer[0] = 0x00;
265 radio->buffer[1] = 0x55; 240 radio->buffer[1] = 0x55;
@@ -275,14 +250,11 @@ static int amradio_set_stereo(struct amradio_device *radio, char argument)
275 250
276 if (retval < 0 || size != BUFFER_LENGTH) { 251 if (retval < 0 || size != BUFFER_LENGTH) {
277 radio->stereo = -1; 252 radio->stereo = -1;
278 mutex_unlock(&radio->lock);
279 return retval; 253 return retval;
280 } 254 }
281 255
282 radio->stereo = 1; 256 radio->stereo = 1;
283 257
284 mutex_unlock(&radio->lock);
285
286 return retval; 258 return retval;
287} 259}
288 260
@@ -325,12 +297,18 @@ static int vidioc_g_tuner(struct file *file, void *priv,
325 struct amradio_device *radio = video_get_drvdata(video_devdata(file)); 297 struct amradio_device *radio = video_get_drvdata(video_devdata(file));
326 int retval; 298 int retval;
327 299
300 mutex_lock(&radio->lock);
301
328 /* safety check */ 302 /* safety check */
329 if (radio->removed) 303 if (radio->removed) {
330 return -EIO; 304 retval = -EIO;
305 goto unlock;
306 }
331 307
332 if (v->index > 0) 308 if (v->index > 0) {
333 return -EINVAL; 309 retval = -EINVAL;
310 goto unlock;
311 }
334 312
335/* TODO: Add function which look is signal stereo or not 313/* TODO: Add function which look is signal stereo or not
336 * amradio_getstat(radio); 314 * amradio_getstat(radio);
@@ -357,7 +335,10 @@ static int vidioc_g_tuner(struct file *file, void *priv,
357 v->audmode = V4L2_TUNER_MODE_MONO; 335 v->audmode = V4L2_TUNER_MODE_MONO;
358 v->signal = 0xffff; /* Can't get the signal strength, sad.. */ 336 v->signal = 0xffff; /* Can't get the signal strength, sad.. */
359 v->afc = 0; /* Don't know what is this */ 337 v->afc = 0; /* Don't know what is this */
360 return 0; 338
339unlock:
340 mutex_unlock(&radio->lock);
341 return retval;
361} 342}
362 343
363/* vidioc_s_tuner - set tuner attributes */ 344/* vidioc_s_tuner - set tuner attributes */
@@ -367,12 +348,18 @@ static int vidioc_s_tuner(struct file *file, void *priv,
367 struct amradio_device *radio = video_get_drvdata(video_devdata(file)); 348 struct amradio_device *radio = video_get_drvdata(video_devdata(file));
368 int retval; 349 int retval;
369 350
351 mutex_lock(&radio->lock);
352
370 /* safety check */ 353 /* safety check */
371 if (radio->removed) 354 if (radio->removed) {
372 return -EIO; 355 retval = -EIO;
356 goto unlock;
357 }
373 358
374 if (v->index > 0) 359 if (v->index > 0) {
375 return -EINVAL; 360 retval = -EINVAL;
361 goto unlock;
362 }
376 363
377 /* mono/stereo selector */ 364 /* mono/stereo selector */
378 switch (v->audmode) { 365 switch (v->audmode) {
@@ -389,10 +376,12 @@ static int vidioc_s_tuner(struct file *file, void *priv,
389 "set stereo failed\n"); 376 "set stereo failed\n");
390 break; 377 break;
391 default: 378 default:
392 return -EINVAL; 379 retval = -EINVAL;
393 } 380 }
394 381
395 return 0; 382unlock:
383 mutex_unlock(&radio->lock);
384 return retval;
396} 385}
397 386
398/* vidioc_s_frequency - set tuner radio frequency */ 387/* vidioc_s_frequency - set tuner radio frequency */
@@ -402,19 +391,24 @@ static int vidioc_s_frequency(struct file *file, void *priv,
402 struct amradio_device *radio = video_get_drvdata(video_devdata(file)); 391 struct amradio_device *radio = video_get_drvdata(video_devdata(file));
403 int retval; 392 int retval;
404 393
394 mutex_lock(&radio->lock);
395
405 /* safety check */ 396 /* safety check */
406 if (radio->removed) 397 if (radio->removed) {
407 return -EIO; 398 retval = -EIO;
399 goto unlock;
400 }
408 401
409 mutex_lock(&radio->lock);
410 radio->curfreq = f->frequency; 402 radio->curfreq = f->frequency;
411 mutex_unlock(&radio->lock);
412 403
413 retval = amradio_setfreq(radio, radio->curfreq); 404 retval = amradio_setfreq(radio, radio->curfreq);
414 if (retval < 0) 405 if (retval < 0)
415 amradio_dev_warn(&radio->videodev->dev, 406 amradio_dev_warn(&radio->videodev->dev,
416 "set frequency failed\n"); 407 "set frequency failed\n");
417 return 0; 408
409unlock:
410 mutex_unlock(&radio->lock);
411 return retval;
418} 412}
419 413
420/* vidioc_g_frequency - get tuner radio frequency */ 414/* vidioc_g_frequency - get tuner radio frequency */
@@ -422,14 +416,22 @@ static int vidioc_g_frequency(struct file *file, void *priv,
422 struct v4l2_frequency *f) 416 struct v4l2_frequency *f)
423{ 417{
424 struct amradio_device *radio = video_get_drvdata(video_devdata(file)); 418 struct amradio_device *radio = video_get_drvdata(video_devdata(file));
419 int retval = 0;
420
421 mutex_lock(&radio->lock);
425 422
426 /* safety check */ 423 /* safety check */
427 if (radio->removed) 424 if (radio->removed) {
428 return -EIO; 425 retval = -EIO;
426 goto unlock;
427 }
429 428
430 f->type = V4L2_TUNER_RADIO; 429 f->type = V4L2_TUNER_RADIO;
431 f->frequency = radio->curfreq; 430 f->frequency = radio->curfreq;
432 return 0; 431
432unlock:
433 mutex_unlock(&radio->lock);
434 return retval;
433} 435}
434 436
435/* vidioc_queryctrl - enumerate control items */ 437/* vidioc_queryctrl - enumerate control items */
@@ -449,17 +451,26 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
449 struct v4l2_control *ctrl) 451 struct v4l2_control *ctrl)
450{ 452{
451 struct amradio_device *radio = video_get_drvdata(video_devdata(file)); 453 struct amradio_device *radio = video_get_drvdata(video_devdata(file));
454 int retval = -EINVAL;
455
456 mutex_lock(&radio->lock);
452 457
453 /* safety check */ 458 /* safety check */
454 if (radio->removed) 459 if (radio->removed) {
455 return -EIO; 460 retval = -EIO;
461 goto unlock;
462 }
456 463
457 switch (ctrl->id) { 464 switch (ctrl->id) {
458 case V4L2_CID_AUDIO_MUTE: 465 case V4L2_CID_AUDIO_MUTE:
459 ctrl->value = radio->muted; 466 ctrl->value = radio->muted;
460 return 0; 467 retval = 0;
468 break;
461 } 469 }
462 return -EINVAL; 470
471unlock:
472 mutex_unlock(&radio->lock);
473 return retval;
463} 474}
464 475
465/* vidioc_s_ctrl - set the value of a control */ 476/* vidioc_s_ctrl - set the value of a control */
@@ -467,11 +478,15 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
467 struct v4l2_control *ctrl) 478 struct v4l2_control *ctrl)
468{ 479{
469 struct amradio_device *radio = video_get_drvdata(video_devdata(file)); 480 struct amradio_device *radio = video_get_drvdata(video_devdata(file));
470 int retval; 481 int retval = -EINVAL;
482
483 mutex_lock(&radio->lock);
471 484
472 /* safety check */ 485 /* safety check */
473 if (radio->removed) 486 if (radio->removed) {
474 return -EIO; 487 retval = -EIO;
488 goto unlock;
489 }
475 490
476 switch (ctrl->id) { 491 switch (ctrl->id) {
477 case V4L2_CID_AUDIO_MUTE: 492 case V4L2_CID_AUDIO_MUTE:
@@ -480,19 +495,20 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
480 if (retval < 0) { 495 if (retval < 0) {
481 amradio_dev_warn(&radio->videodev->dev, 496 amradio_dev_warn(&radio->videodev->dev,
482 "amradio_stop failed\n"); 497 "amradio_stop failed\n");
483 return -1;
484 } 498 }
485 } else { 499 } else {
486 retval = amradio_set_mute(radio, AMRADIO_START); 500 retval = amradio_set_mute(radio, AMRADIO_START);
487 if (retval < 0) { 501 if (retval < 0) {
488 amradio_dev_warn(&radio->videodev->dev, 502 amradio_dev_warn(&radio->videodev->dev,
489 "amradio_start failed\n"); 503 "amradio_start failed\n");
490 return -1;
491 } 504 }
492 } 505 }
493 return 0; 506 break;
494 } 507 }
495 return -EINVAL; 508
509unlock:
510 mutex_unlock(&radio->lock);
511 return retval;
496} 512}
497 513
498/* vidioc_g_audio - get audio attributes */ 514/* vidioc_g_audio - get audio attributes */
@@ -535,9 +551,14 @@ static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
535static int usb_amradio_open(struct file *file) 551static int usb_amradio_open(struct file *file)
536{ 552{
537 struct amradio_device *radio = video_get_drvdata(video_devdata(file)); 553 struct amradio_device *radio = video_get_drvdata(video_devdata(file));
538 int retval; 554 int retval = 0;
539 555
540 lock_kernel(); 556 mutex_lock(&radio->lock);
557
558 if (radio->removed) {
559 retval = -EIO;
560 goto unlock;
561 }
541 562
542 radio->users = 1; 563 radio->users = 1;
543 radio->muted = 1; 564 radio->muted = 1;
@@ -547,8 +568,7 @@ static int usb_amradio_open(struct file *file)
547 amradio_dev_warn(&radio->videodev->dev, 568 amradio_dev_warn(&radio->videodev->dev,
548 "radio did not start up properly\n"); 569 "radio did not start up properly\n");
549 radio->users = 0; 570 radio->users = 0;
550 unlock_kernel(); 571 goto unlock;
551 return -EIO;
552 } 572 }
553 573
554 retval = amradio_set_stereo(radio, WANT_STEREO); 574 retval = amradio_set_stereo(radio, WANT_STEREO);
@@ -561,22 +581,25 @@ static int usb_amradio_open(struct file *file)
561 amradio_dev_warn(&radio->videodev->dev, 581 amradio_dev_warn(&radio->videodev->dev,
562 "set frequency failed\n"); 582 "set frequency failed\n");
563 583
564 unlock_kernel(); 584unlock:
565 return 0; 585 mutex_unlock(&radio->lock);
586 return retval;
566} 587}
567 588
568/*close device */ 589/*close device */
569static int usb_amradio_close(struct file *file) 590static int usb_amradio_close(struct file *file)
570{ 591{
571 struct amradio_device *radio = video_get_drvdata(video_devdata(file)); 592 struct amradio_device *radio = video_get_drvdata(video_devdata(file));
572 int retval; 593 int retval = 0;
573
574 if (!radio)
575 return -ENODEV;
576 594
577 mutex_lock(&radio->lock); 595 mutex_lock(&radio->lock);
596
597 if (radio->removed) {
598 retval = -EIO;
599 goto unlock;
600 }
601
578 radio->users = 0; 602 radio->users = 0;
579 mutex_unlock(&radio->lock);
580 603
581 if (!radio->removed) { 604 if (!radio->removed) {
582 retval = amradio_set_mute(radio, AMRADIO_STOP); 605 retval = amradio_set_mute(radio, AMRADIO_STOP);
@@ -585,7 +608,9 @@ static int usb_amradio_close(struct file *file)
585 "amradio_stop failed\n"); 608 "amradio_stop failed\n");
586 } 609 }
587 610
588 return 0; 611unlock:
612 mutex_unlock(&radio->lock);
613 return retval;
589} 614}
590 615
591/* Suspend device - stop device. Need to be checked and fixed */ 616/* Suspend device - stop device. Need to be checked and fixed */
@@ -594,12 +619,15 @@ static int usb_amradio_suspend(struct usb_interface *intf, pm_message_t message)
594 struct amradio_device *radio = usb_get_intfdata(intf); 619 struct amradio_device *radio = usb_get_intfdata(intf);
595 int retval; 620 int retval;
596 621
622 mutex_lock(&radio->lock);
623
597 retval = amradio_set_mute(radio, AMRADIO_STOP); 624 retval = amradio_set_mute(radio, AMRADIO_STOP);
598 if (retval < 0) 625 if (retval < 0)
599 dev_warn(&intf->dev, "amradio_stop failed\n"); 626 dev_warn(&intf->dev, "amradio_stop failed\n");
600 627
601 dev_info(&intf->dev, "going into suspend..\n"); 628 dev_info(&intf->dev, "going into suspend..\n");
602 629
630 mutex_unlock(&radio->lock);
603 return 0; 631 return 0;
604} 632}
605 633
@@ -609,12 +637,15 @@ static int usb_amradio_resume(struct usb_interface *intf)
609 struct amradio_device *radio = usb_get_intfdata(intf); 637 struct amradio_device *radio = usb_get_intfdata(intf);
610 int retval; 638 int retval;
611 639
640 mutex_lock(&radio->lock);
641
612 retval = amradio_set_mute(radio, AMRADIO_START); 642 retval = amradio_set_mute(radio, AMRADIO_START);
613 if (retval < 0) 643 if (retval < 0)
614 dev_warn(&intf->dev, "amradio_start failed\n"); 644 dev_warn(&intf->dev, "amradio_start failed\n");
615 645
616 dev_info(&intf->dev, "coming out of suspend..\n"); 646 dev_info(&intf->dev, "coming out of suspend..\n");
617 647
648 mutex_unlock(&radio->lock);
618 return 0; 649 return 0;
619} 650}
620 651