aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/cdrom/cdrom.c
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
committerGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
commitc71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch)
treeecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /drivers/cdrom/cdrom.c
parentea53c912f8a86a8567697115b6a0d8152beee5c8 (diff)
parent6a00f206debf8a5c8899055726ad127dbeeed098 (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.c69
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
322.00 Dec 2, 1997 -- Erik Andersen <andersee@debian.org> 322.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;
1018err_release: 1019err_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 */
1413static 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
1423unsigned 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}
1433EXPORT_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