Commit 737f1cd8 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'for-5.16/cdrom-2021-10-29' of git://git.kernel.dk/linux-block

Pull CDROM updates from Jens Axboe:
 "On behalf of Phillip, here are the CDROM updates for the 5.16-rc1
  merge window:

   - Add ioctl for improved media change detection (Lukas)

   - Reformat some documentation (Phillip)

   - Redundant variable removal (luo)"

* tag 'for-5.16/cdrom-2021-10-29' of git://git.kernel.dk/linux-block:
  cdrom: Remove redundant variable and its assignment
  cdrom: docs: reformat table in Documentation/userspace-api/ioctl/cdrom.rst
  drivers/cdrom: improved ioctl for media change detection
parents fcaec17b bbc3925c
...@@ -907,6 +907,17 @@ commands can be identified by the underscores in their names. ...@@ -907,6 +907,17 @@ commands can be identified by the underscores in their names.
specifies the slot for which the information is given. The special specifies the slot for which the information is given. The special
value *CDSL_CURRENT* requests that information about the currently value *CDSL_CURRENT* requests that information about the currently
selected slot be returned. selected slot be returned.
`CDROM_TIMED_MEDIA_CHANGE`
Checks whether the disc has been changed since a user supplied time
and returns the time of the last disc change.
*arg* is a pointer to a *cdrom_timed_media_change_info* struct.
*arg->last_media_change* may be set by calling code to signal
the timestamp of the last known media change (by the caller).
Upon successful return, this ioctl call will set
*arg->last_media_change* to the latest media change timestamp (in ms)
known by the kernel/driver and set *arg->has_changed* to 1 if
that timestamp is more recent than the timestamp set by the caller.
`CDROM_DRIVE_STATUS` `CDROM_DRIVE_STATUS`
Returns the status of the drive by a call to Returns the status of the drive by a call to
*drive_status()*. Return values are defined in cdrom_drive_status_. *drive_status()*. Return values are defined in cdrom_drive_status_.
......
...@@ -13,61 +13,64 @@ in drivers/cdrom/cdrom.c and drivers/block/scsi_ioctl.c ...@@ -13,61 +13,64 @@ in drivers/cdrom/cdrom.c and drivers/block/scsi_ioctl.c
ioctl values are listed in <linux/cdrom.h>. As of this writing, they ioctl values are listed in <linux/cdrom.h>. As of this writing, they
are as follows: are as follows:
====================== =============================================== ======================== ===============================================
CDROMPAUSE Pause Audio Operation CDROMPAUSE Pause Audio Operation
CDROMRESUME Resume paused Audio Operation CDROMRESUME Resume paused Audio Operation
CDROMPLAYMSF Play Audio MSF (struct cdrom_msf) CDROMPLAYMSF Play Audio MSF (struct cdrom_msf)
CDROMPLAYTRKIND Play Audio Track/index (struct cdrom_ti) CDROMPLAYTRKIND Play Audio Track/index (struct cdrom_ti)
CDROMREADTOCHDR Read TOC header (struct cdrom_tochdr) CDROMREADTOCHDR Read TOC header (struct cdrom_tochdr)
CDROMREADTOCENTRY Read TOC entry (struct cdrom_tocentry) CDROMREADTOCENTRY Read TOC entry (struct cdrom_tocentry)
CDROMSTOP Stop the cdrom drive CDROMSTOP Stop the cdrom drive
CDROMSTART Start the cdrom drive CDROMSTART Start the cdrom drive
CDROMEJECT Ejects the cdrom media CDROMEJECT Ejects the cdrom media
CDROMVOLCTRL Control output volume (struct cdrom_volctrl) CDROMVOLCTRL Control output volume (struct cdrom_volctrl)
CDROMSUBCHNL Read subchannel data (struct cdrom_subchnl) CDROMSUBCHNL Read subchannel data (struct cdrom_subchnl)
CDROMREADMODE2 Read CDROM mode 2 data (2336 Bytes) CDROMREADMODE2 Read CDROM mode 2 data (2336 Bytes)
(struct cdrom_read) (struct cdrom_read)
CDROMREADMODE1 Read CDROM mode 1 data (2048 Bytes) CDROMREADMODE1 Read CDROM mode 1 data (2048 Bytes)
(struct cdrom_read) (struct cdrom_read)
CDROMREADAUDIO (struct cdrom_read_audio) CDROMREADAUDIO (struct cdrom_read_audio)
CDROMEJECT_SW enable(1)/disable(0) auto-ejecting CDROMEJECT_SW enable(1)/disable(0) auto-ejecting
CDROMMULTISESSION Obtain the start-of-last-session CDROMMULTISESSION Obtain the start-of-last-session
address of multi session disks address of multi session disks
(struct cdrom_multisession) (struct cdrom_multisession)
CDROM_GET_MCN Obtain the "Universal Product Code" CDROM_GET_MCN Obtain the "Universal Product Code"
if available (struct cdrom_mcn) if available (struct cdrom_mcn)
CDROM_GET_UPC Deprecated, use CDROM_GET_MCN instead. CDROM_GET_UPC Deprecated, use CDROM_GET_MCN instead.
CDROMRESET hard-reset the drive CDROMRESET hard-reset the drive
CDROMVOLREAD Get the drive's volume setting CDROMVOLREAD Get the drive's volume setting
(struct cdrom_volctrl) (struct cdrom_volctrl)
CDROMREADRAW read data in raw mode (2352 Bytes) CDROMREADRAW read data in raw mode (2352 Bytes)
(struct cdrom_read) (struct cdrom_read)
CDROMREADCOOKED read data in cooked mode CDROMREADCOOKED read data in cooked mode
CDROMSEEK seek msf address CDROMSEEK seek msf address
CDROMPLAYBLK scsi-cd only, (struct cdrom_blk) CDROMPLAYBLK scsi-cd only, (struct cdrom_blk)
CDROMREADALL read all 2646 bytes CDROMREADALL read all 2646 bytes
CDROMGETSPINDOWN return 4-bit spindown value CDROMGETSPINDOWN return 4-bit spindown value
CDROMSETSPINDOWN set 4-bit spindown value CDROMSETSPINDOWN set 4-bit spindown value
CDROMCLOSETRAY pendant of CDROMEJECT CDROMCLOSETRAY pendant of CDROMEJECT
CDROM_SET_OPTIONS Set behavior options CDROM_SET_OPTIONS Set behavior options
CDROM_CLEAR_OPTIONS Clear behavior options CDROM_CLEAR_OPTIONS Clear behavior options
CDROM_SELECT_SPEED Set the CD-ROM speed CDROM_SELECT_SPEED Set the CD-ROM speed
CDROM_SELECT_DISC Select disc (for juke-boxes) CDROM_SELECT_DISC Select disc (for juke-boxes)
CDROM_MEDIA_CHANGED Check is media changed CDROM_MEDIA_CHANGED Check is media changed
CDROM_DRIVE_STATUS Get tray position, etc. CDROM_TIMED_MEDIA_CHANGE Check if media changed
CDROM_DISC_STATUS Get disc type, etc. since given time
CDROM_CHANGER_NSLOTS Get number of slots (struct cdrom_timed_media_change_info)
CDROM_LOCKDOOR lock or unlock door CDROM_DRIVE_STATUS Get tray position, etc.
CDROM_DEBUG Turn debug messages on/off CDROM_DISC_STATUS Get disc type, etc.
CDROM_GET_CAPABILITY get capabilities CDROM_CHANGER_NSLOTS Get number of slots
CDROMAUDIOBUFSIZ set the audio buffer size CDROM_LOCKDOOR lock or unlock door
DVD_READ_STRUCT Read structure CDROM_DEBUG Turn debug messages on/off
DVD_WRITE_STRUCT Write structure CDROM_GET_CAPABILITY get capabilities
DVD_AUTH Authentication CDROMAUDIOBUFSIZ set the audio buffer size
CDROM_SEND_PACKET send a packet to the drive DVD_READ_STRUCT Read structure
CDROM_NEXT_WRITABLE get next writable block DVD_WRITE_STRUCT Write structure
CDROM_LAST_WRITTEN get last block written on disc DVD_AUTH Authentication
====================== =============================================== CDROM_SEND_PACKET send a packet to the drive
CDROM_NEXT_WRITABLE get next writable block
CDROM_LAST_WRITTEN get last block written on disc
======================== ===============================================
The information that follows was determined from reading kernel source The information that follows was determined from reading kernel source
......
...@@ -344,6 +344,12 @@ static void cdrom_sysctl_register(void); ...@@ -344,6 +344,12 @@ static void cdrom_sysctl_register(void);
static LIST_HEAD(cdrom_list); static LIST_HEAD(cdrom_list);
static void signal_media_change(struct cdrom_device_info *cdi)
{
cdi->mc_flags = 0x3; /* set media changed bits, on both queues */
cdi->last_media_change_ms = ktime_to_ms(ktime_get());
}
int cdrom_dummy_generic_packet(struct cdrom_device_info *cdi, int cdrom_dummy_generic_packet(struct cdrom_device_info *cdi,
struct packet_command *cgc) struct packet_command *cgc)
{ {
...@@ -616,6 +622,7 @@ int register_cdrom(struct gendisk *disk, struct cdrom_device_info *cdi) ...@@ -616,6 +622,7 @@ int register_cdrom(struct gendisk *disk, struct cdrom_device_info *cdi)
ENSURE(cdo, generic_packet, CDC_GENERIC_PACKET); ENSURE(cdo, generic_packet, CDC_GENERIC_PACKET);
cdi->mc_flags = 0; cdi->mc_flags = 0;
cdi->options = CDO_USE_FFLAGS; cdi->options = CDO_USE_FFLAGS;
cdi->last_media_change_ms = ktime_to_ms(ktime_get());
if (autoclose == 1 && CDROM_CAN(CDC_CLOSE_TRAY)) if (autoclose == 1 && CDROM_CAN(CDC_CLOSE_TRAY))
cdi->options |= (int) CDO_AUTO_CLOSE; cdi->options |= (int) CDO_AUTO_CLOSE;
...@@ -864,7 +871,7 @@ static void cdrom_mmc3_profile(struct cdrom_device_info *cdi) ...@@ -864,7 +871,7 @@ static void cdrom_mmc3_profile(struct cdrom_device_info *cdi)
{ {
struct packet_command cgc; struct packet_command cgc;
char buffer[32]; char buffer[32];
int ret, mmc3_profile; int mmc3_profile;
init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ); init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ);
...@@ -874,7 +881,7 @@ static void cdrom_mmc3_profile(struct cdrom_device_info *cdi) ...@@ -874,7 +881,7 @@ static void cdrom_mmc3_profile(struct cdrom_device_info *cdi)
cgc.cmd[8] = sizeof(buffer); /* Allocation Length */ cgc.cmd[8] = sizeof(buffer); /* Allocation Length */
cgc.quiet = 1; cgc.quiet = 1;
if ((ret = cdi->ops->generic_packet(cdi, &cgc))) if (cdi->ops->generic_packet(cdi, &cgc))
mmc3_profile = 0xffff; mmc3_profile = 0xffff;
else else
mmc3_profile = (buffer[6] << 8) | buffer[7]; mmc3_profile = (buffer[6] << 8) | buffer[7];
...@@ -1421,8 +1428,7 @@ static int cdrom_select_disc(struct cdrom_device_info *cdi, int slot) ...@@ -1421,8 +1428,7 @@ static int cdrom_select_disc(struct cdrom_device_info *cdi, int slot)
cdi->ops->check_events(cdi, 0, slot); cdi->ops->check_events(cdi, 0, slot);
if (slot == CDSL_NONE) { if (slot == CDSL_NONE) {
/* set media changed bits, on both queues */ signal_media_change(cdi);
cdi->mc_flags = 0x3;
return cdrom_load_unload(cdi, -1); return cdrom_load_unload(cdi, -1);
} }
...@@ -1455,7 +1461,7 @@ static int cdrom_select_disc(struct cdrom_device_info *cdi, int slot) ...@@ -1455,7 +1461,7 @@ static int cdrom_select_disc(struct cdrom_device_info *cdi, int slot)
slot = curslot; slot = curslot;
/* set media changed bits on both queues */ /* set media changed bits on both queues */
cdi->mc_flags = 0x3; signal_media_change(cdi);
if ((ret = cdrom_load_unload(cdi, slot))) if ((ret = cdrom_load_unload(cdi, slot)))
return ret; return ret;
...@@ -1521,7 +1527,7 @@ int media_changed(struct cdrom_device_info *cdi, int queue) ...@@ -1521,7 +1527,7 @@ int media_changed(struct cdrom_device_info *cdi, int queue)
cdi->ioctl_events = 0; cdi->ioctl_events = 0;
if (changed) { if (changed) {
cdi->mc_flags = 0x3; /* set bit on both queues */ signal_media_change(cdi);
ret |= 1; ret |= 1;
cdi->media_written = 0; cdi->media_written = 0;
} }
...@@ -2336,6 +2342,49 @@ static int cdrom_ioctl_media_changed(struct cdrom_device_info *cdi, ...@@ -2336,6 +2342,49 @@ static int cdrom_ioctl_media_changed(struct cdrom_device_info *cdi,
return ret; return ret;
} }
/*
* Media change detection with timing information.
*
* arg is a pointer to a cdrom_timed_media_change_info struct.
* arg->last_media_change may be set by calling code to signal
* the timestamp (in ms) of the last known media change (by the caller).
* Upon successful return, ioctl call will set arg->last_media_change
* to the latest media change timestamp known by the kernel/driver
* and set arg->has_changed to 1 if that timestamp is more recent
* than the timestamp set by the caller.
*/
static int cdrom_ioctl_timed_media_change(struct cdrom_device_info *cdi,
unsigned long arg)
{
int ret;
struct cdrom_timed_media_change_info __user *info;
struct cdrom_timed_media_change_info tmp_info;
if (!CDROM_CAN(CDC_MEDIA_CHANGED))
return -ENOSYS;
info = (struct cdrom_timed_media_change_info __user *)arg;
cd_dbg(CD_DO_IOCTL, "entering CDROM_TIMED_MEDIA_CHANGE\n");
ret = cdrom_ioctl_media_changed(cdi, CDSL_CURRENT);
if (ret < 0)
return ret;
if (copy_from_user(&tmp_info, info, sizeof(tmp_info)) != 0)
return -EFAULT;
tmp_info.media_flags = 0;
if (tmp_info.last_media_change - cdi->last_media_change_ms < 0)
tmp_info.media_flags |= MEDIA_CHANGED_FLAG;
tmp_info.last_media_change = cdi->last_media_change_ms;
if (copy_to_user(info, &tmp_info, sizeof(*info)) != 0)
return -EFAULT;
return 0;
}
static int cdrom_ioctl_set_options(struct cdrom_device_info *cdi, static int cdrom_ioctl_set_options(struct cdrom_device_info *cdi,
unsigned long arg) unsigned long arg)
{ {
...@@ -3313,6 +3362,8 @@ int cdrom_ioctl(struct cdrom_device_info *cdi, struct block_device *bdev, ...@@ -3313,6 +3362,8 @@ int cdrom_ioctl(struct cdrom_device_info *cdi, struct block_device *bdev,
return cdrom_ioctl_eject_sw(cdi, arg); return cdrom_ioctl_eject_sw(cdi, arg);
case CDROM_MEDIA_CHANGED: case CDROM_MEDIA_CHANGED:
return cdrom_ioctl_media_changed(cdi, arg); return cdrom_ioctl_media_changed(cdi, arg);
case CDROM_TIMED_MEDIA_CHANGE:
return cdrom_ioctl_timed_media_change(cdi, arg);
case CDROM_SET_OPTIONS: case CDROM_SET_OPTIONS:
return cdrom_ioctl_set_options(cdi, arg); return cdrom_ioctl_set_options(cdi, arg);
case CDROM_CLEAR_OPTIONS: case CDROM_CLEAR_OPTIONS:
......
...@@ -64,6 +64,7 @@ struct cdrom_device_info { ...@@ -64,6 +64,7 @@ struct cdrom_device_info {
int for_data; int for_data;
int (*exit)(struct cdrom_device_info *); int (*exit)(struct cdrom_device_info *);
int mrw_mode_page; int mrw_mode_page;
__s64 last_media_change_ms;
}; };
struct cdrom_device_ops { struct cdrom_device_ops {
......
...@@ -147,6 +147,8 @@ ...@@ -147,6 +147,8 @@
#define CDROM_NEXT_WRITABLE 0x5394 /* get next writable block */ #define CDROM_NEXT_WRITABLE 0x5394 /* get next writable block */
#define CDROM_LAST_WRITTEN 0x5395 /* get last block written on disc */ #define CDROM_LAST_WRITTEN 0x5395 /* get last block written on disc */
#define CDROM_TIMED_MEDIA_CHANGE 0x5396 /* get the timestamp of the last media change */
/******************************************************* /*******************************************************
* CDROM IOCTL structures * CDROM IOCTL structures
*******************************************************/ *******************************************************/
...@@ -295,6 +297,23 @@ struct cdrom_generic_command ...@@ -295,6 +297,23 @@ struct cdrom_generic_command
}; };
}; };
/* This struct is used by CDROM_TIMED_MEDIA_CHANGE */
struct cdrom_timed_media_change_info {
__s64 last_media_change; /* Timestamp of the last detected media
* change in ms. May be set by caller,
* updated upon successful return of
* ioctl.
*/
__u64 media_flags; /* Flags returned by ioctl to indicate
* media status.
*/
};
#define MEDIA_CHANGED_FLAG 0x1 /* Last detected media change was more
* recent than last_media_change set by
* caller.
*/
/* other bits of media_flags available for future use */
/* /*
* A CD-ROM physical sector size is 2048, 2052, 2056, 2324, 2332, 2336, * A CD-ROM physical sector size is 2048, 2052, 2056, 2324, 2332, 2336,
* 2340, or 2352 bytes long. * 2340, or 2352 bytes long.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment