diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /drivers/cdrom/cdrom.c | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (diff) |
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts:
litmus/sched_cedf.c
Diffstat (limited to 'drivers/cdrom/cdrom.c')
-rw-r--r-- | drivers/cdrom/cdrom.c | 69 |
1 files changed, 60 insertions, 9 deletions
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index af13c62dc473..75fb965b8f72 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c | |||
@@ -30,7 +30,7 @@ | |||
30 | changelog for the 1.x series, David? | 30 | changelog for the 1.x series, David? |
31 | 31 | ||
32 | 2.00 Dec 2, 1997 -- Erik Andersen <andersee@debian.org> | 32 | 2.00 Dec 2, 1997 -- Erik Andersen <andersee@debian.org> |
33 | -- New maintainer! As David A. van Leeuwen has been too busy to activly | 33 | -- New maintainer! As David A. van Leeuwen has been too busy to actively |
34 | maintain and improve this driver, I am now carrying on the torch. If | 34 | maintain and improve this driver, I am now carrying on the torch. If |
35 | you have a problem with this driver, please feel free to contact me. | 35 | you have a problem with this driver, please feel free to contact me. |
36 | 36 | ||
@@ -409,7 +409,8 @@ int register_cdrom(struct cdrom_device_info *cdi) | |||
409 | } | 409 | } |
410 | 410 | ||
411 | ENSURE(drive_status, CDC_DRIVE_STATUS ); | 411 | ENSURE(drive_status, CDC_DRIVE_STATUS ); |
412 | ENSURE(media_changed, CDC_MEDIA_CHANGED); | 412 | if (cdo->check_events == NULL && cdo->media_changed == NULL) |
413 | *change_capability = ~(CDC_MEDIA_CHANGED | CDC_SELECT_DISC); | ||
413 | ENSURE(tray_move, CDC_CLOSE_TRAY | CDC_OPEN_TRAY); | 414 | ENSURE(tray_move, CDC_CLOSE_TRAY | CDC_OPEN_TRAY); |
414 | ENSURE(lock_door, CDC_LOCK); | 415 | ENSURE(lock_door, CDC_LOCK); |
415 | ENSURE(select_speed, CDC_SELECT_SPEED); | 416 | ENSURE(select_speed, CDC_SELECT_SPEED); |
@@ -985,6 +986,9 @@ int cdrom_open(struct cdrom_device_info *cdi, struct block_device *bdev, fmode_t | |||
985 | 986 | ||
986 | cdinfo(CD_OPEN, "entering cdrom_open\n"); | 987 | cdinfo(CD_OPEN, "entering cdrom_open\n"); |
987 | 988 | ||
989 | /* open is event synchronization point, check events first */ | ||
990 | check_disk_change(bdev); | ||
991 | |||
988 | /* if this was a O_NONBLOCK open and we should honor the flags, | 992 | /* if this was a O_NONBLOCK open and we should honor the flags, |
989 | * do a quick open without drive/disc integrity checks. */ | 993 | * do a quick open without drive/disc integrity checks. */ |
990 | cdi->use_count++; | 994 | cdi->use_count++; |
@@ -1011,9 +1015,6 @@ int cdrom_open(struct cdrom_device_info *cdi, struct block_device *bdev, fmode_t | |||
1011 | 1015 | ||
1012 | cdinfo(CD_OPEN, "Use count for \"/dev/%s\" now %d\n", | 1016 | cdinfo(CD_OPEN, "Use count for \"/dev/%s\" now %d\n", |
1013 | cdi->name, cdi->use_count); | 1017 | cdi->name, cdi->use_count); |
1014 | /* Do this on open. Don't wait for mount, because they might | ||
1015 | not be mounting, but opening with O_NONBLOCK */ | ||
1016 | check_disk_change(bdev); | ||
1017 | return 0; | 1018 | return 0; |
1018 | err_release: | 1019 | err_release: |
1019 | if (CDROM_CAN(CDC_LOCK) && cdi->options & CDO_LOCK) { | 1020 | if (CDROM_CAN(CDC_LOCK) && cdi->options & CDO_LOCK) { |
@@ -1348,7 +1349,10 @@ static int cdrom_select_disc(struct cdrom_device_info *cdi, int slot) | |||
1348 | if (!CDROM_CAN(CDC_SELECT_DISC)) | 1349 | if (!CDROM_CAN(CDC_SELECT_DISC)) |
1349 | return -EDRIVE_CANT_DO_THIS; | 1350 | return -EDRIVE_CANT_DO_THIS; |
1350 | 1351 | ||
1351 | (void) cdi->ops->media_changed(cdi, slot); | 1352 | if (cdi->ops->check_events) |
1353 | cdi->ops->check_events(cdi, 0, slot); | ||
1354 | else | ||
1355 | cdi->ops->media_changed(cdi, slot); | ||
1352 | 1356 | ||
1353 | if (slot == CDSL_NONE) { | 1357 | if (slot == CDSL_NONE) { |
1354 | /* set media changed bits, on both queues */ | 1358 | /* set media changed bits, on both queues */ |
@@ -1392,6 +1396,42 @@ static int cdrom_select_disc(struct cdrom_device_info *cdi, int slot) | |||
1392 | return slot; | 1396 | return slot; |
1393 | } | 1397 | } |
1394 | 1398 | ||
1399 | /* | ||
1400 | * As cdrom implements an extra ioctl consumer for media changed | ||
1401 | * event, it needs to buffer ->check_events() output, such that event | ||
1402 | * is not lost for both the usual VFS and ioctl paths. | ||
1403 | * cdi->{vfs|ioctl}_events are used to buffer pending events for each | ||
1404 | * path. | ||
1405 | * | ||
1406 | * XXX: Locking is non-existent. cdi->ops->check_events() can be | ||
1407 | * called in parallel and buffering fields are accessed without any | ||
1408 | * exclusion. The original media_changed code had the same problem. | ||
1409 | * It might be better to simply deprecate CDROM_MEDIA_CHANGED ioctl | ||
1410 | * and remove this cruft altogether. It doesn't have much usefulness | ||
1411 | * at this point. | ||
1412 | */ | ||
1413 | static void cdrom_update_events(struct cdrom_device_info *cdi, | ||
1414 | unsigned int clearing) | ||
1415 | { | ||
1416 | unsigned int events; | ||
1417 | |||
1418 | events = cdi->ops->check_events(cdi, clearing, CDSL_CURRENT); | ||
1419 | cdi->vfs_events |= events; | ||
1420 | cdi->ioctl_events |= events; | ||
1421 | } | ||
1422 | |||
1423 | unsigned int cdrom_check_events(struct cdrom_device_info *cdi, | ||
1424 | unsigned int clearing) | ||
1425 | { | ||
1426 | unsigned int events; | ||
1427 | |||
1428 | cdrom_update_events(cdi, clearing); | ||
1429 | events = cdi->vfs_events; | ||
1430 | cdi->vfs_events = 0; | ||
1431 | return events; | ||
1432 | } | ||
1433 | EXPORT_SYMBOL(cdrom_check_events); | ||
1434 | |||
1395 | /* We want to make media_changed accessible to the user through an | 1435 | /* We want to make media_changed accessible to the user through an |
1396 | * ioctl. The main problem now is that we must double-buffer the | 1436 | * ioctl. The main problem now is that we must double-buffer the |
1397 | * low-level implementation, to assure that the VFS and the user both | 1437 | * low-level implementation, to assure that the VFS and the user both |
@@ -1403,15 +1443,26 @@ int media_changed(struct cdrom_device_info *cdi, int queue) | |||
1403 | { | 1443 | { |
1404 | unsigned int mask = (1 << (queue & 1)); | 1444 | unsigned int mask = (1 << (queue & 1)); |
1405 | int ret = !!(cdi->mc_flags & mask); | 1445 | int ret = !!(cdi->mc_flags & mask); |
1446 | bool changed; | ||
1406 | 1447 | ||
1407 | if (!CDROM_CAN(CDC_MEDIA_CHANGED)) | 1448 | if (!CDROM_CAN(CDC_MEDIA_CHANGED)) |
1408 | return ret; | 1449 | return ret; |
1450 | |||
1409 | /* changed since last call? */ | 1451 | /* changed since last call? */ |
1410 | if (cdi->ops->media_changed(cdi, CDSL_CURRENT)) { | 1452 | if (cdi->ops->check_events) { |
1453 | BUG_ON(!queue); /* shouldn't be called from VFS path */ | ||
1454 | cdrom_update_events(cdi, DISK_EVENT_MEDIA_CHANGE); | ||
1455 | changed = cdi->ioctl_events & DISK_EVENT_MEDIA_CHANGE; | ||
1456 | cdi->ioctl_events = 0; | ||
1457 | } else | ||
1458 | changed = cdi->ops->media_changed(cdi, CDSL_CURRENT); | ||
1459 | |||
1460 | if (changed) { | ||
1411 | cdi->mc_flags = 0x3; /* set bit on both queues */ | 1461 | cdi->mc_flags = 0x3; /* set bit on both queues */ |
1412 | ret |= 1; | 1462 | ret |= 1; |
1413 | cdi->media_written = 0; | 1463 | cdi->media_written = 0; |
1414 | } | 1464 | } |
1465 | |||
1415 | cdi->mc_flags &= ~mask; /* clear bit */ | 1466 | cdi->mc_flags &= ~mask; /* clear bit */ |
1416 | return ret; | 1467 | return ret; |
1417 | } | 1468 | } |
@@ -2469,7 +2520,7 @@ static int cdrom_ioctl_drive_status(struct cdrom_device_info *cdi, | |||
2469 | /* | 2520 | /* |
2470 | * Ok, this is where problems start. The current interface for the | 2521 | * Ok, this is where problems start. The current interface for the |
2471 | * CDROM_DISC_STATUS ioctl is flawed. It makes the false assumption that | 2522 | * CDROM_DISC_STATUS ioctl is flawed. It makes the false assumption that |
2472 | * CDs are all CDS_DATA_1 or all CDS_AUDIO, etc. Unfortunatly, while this | 2523 | * CDs are all CDS_DATA_1 or all CDS_AUDIO, etc. Unfortunately, while this |
2473 | * is often the case, it is also very common for CDs to have some tracks | 2524 | * is often the case, it is also very common for CDs to have some tracks |
2474 | * with data, and some tracks with audio. Just because I feel like it, | 2525 | * with data, and some tracks with audio. Just because I feel like it, |
2475 | * I declare the following to be the best way to cope. If the CD has ANY | 2526 | * I declare the following to be the best way to cope. If the CD has ANY |