mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 22:21:40 +00:00
firewire: cdev: add more flexible cycle timer ioctl
The system time from CLOCK_REALTIME is not monotonic, hence problematic for the main user of the FW_CDEV_IOC_GET_CYCLE_TIMER ioctl. This issue exists in its successor ABI, i.e. raw1394, too. http://subversion.ffado.org/ticket/242 We now offer an alternative ioctl which lets the caller choose between CLOCK_REALTIME, CLOCK_MONOTONIC, and CLOCK_MONOTONIC_RAW as source of the local time, very similar to the clock_gettime libc function. The format of the local time return value matches that of clock_gettime (seconds and nanoseconds, instead of a single microseconds value from the existing ioctl). Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
This commit is contained in:
parent
fd6e0c5181
commit
abfe5a01ef
@ -1031,22 +1031,46 @@ static int ioctl_stop_iso(struct client *client, void *buffer)
|
||||
return fw_iso_context_stop(client->iso_context);
|
||||
}
|
||||
|
||||
static int ioctl_get_cycle_timer(struct client *client, void *buffer)
|
||||
static int ioctl_get_cycle_timer2(struct client *client, void *buffer)
|
||||
{
|
||||
struct fw_cdev_get_cycle_timer *request = buffer;
|
||||
struct fw_cdev_get_cycle_timer2 *request = buffer;
|
||||
struct fw_card *card = client->device->card;
|
||||
struct timeval tv;
|
||||
struct timespec ts = {0, 0};
|
||||
u32 cycle_time;
|
||||
int ret = 0;
|
||||
|
||||
local_irq_disable();
|
||||
|
||||
cycle_time = card->driver->get_cycle_time(card);
|
||||
do_gettimeofday(&tv);
|
||||
|
||||
switch (request->clk_id) {
|
||||
case CLOCK_REALTIME: getnstimeofday(&ts); break;
|
||||
case CLOCK_MONOTONIC: do_posix_clock_monotonic_gettime(&ts); break;
|
||||
case CLOCK_MONOTONIC_RAW: getrawmonotonic(&ts); break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
local_irq_enable();
|
||||
|
||||
request->local_time = tv.tv_sec * 1000000ULL + tv.tv_usec;
|
||||
request->cycle_timer = cycle_time;
|
||||
request->tv_sec = ts.tv_sec;
|
||||
request->tv_nsec = ts.tv_nsec;
|
||||
request->cycle_timer = cycle_time;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ioctl_get_cycle_timer(struct client *client, void *buffer)
|
||||
{
|
||||
struct fw_cdev_get_cycle_timer *request = buffer;
|
||||
struct fw_cdev_get_cycle_timer2 ct2;
|
||||
|
||||
ct2.clk_id = CLOCK_REALTIME;
|
||||
ioctl_get_cycle_timer2(client, &ct2);
|
||||
|
||||
request->local_time = ct2.tv_sec * USEC_PER_SEC +
|
||||
ct2.tv_nsec / NSEC_PER_USEC;
|
||||
request->cycle_timer = ct2.cycle_timer;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1320,6 +1344,7 @@ static int (* const ioctl_handlers[])(struct client *client, void *buffer) = {
|
||||
ioctl_get_speed,
|
||||
ioctl_send_broadcast_request,
|
||||
ioctl_send_stream_packet,
|
||||
ioctl_get_cycle_timer2,
|
||||
};
|
||||
|
||||
static int dispatch_ioctl(struct client *client,
|
||||
@ -1341,6 +1366,7 @@ static int dispatch_ioctl(struct client *client,
|
||||
struct fw_cdev_get_cycle_timer _0c;
|
||||
struct fw_cdev_allocate_iso_resource _0d;
|
||||
struct fw_cdev_send_stream_packet _13;
|
||||
struct fw_cdev_get_cycle_timer2 _14;
|
||||
})];
|
||||
int ret;
|
||||
|
||||
|
@ -248,6 +248,9 @@ union fw_cdev_event {
|
||||
#define FW_CDEV_IOC_SEND_BROADCAST_REQUEST _IOW('#', 0x12, struct fw_cdev_send_request)
|
||||
#define FW_CDEV_IOC_SEND_STREAM_PACKET _IOW('#', 0x13, struct fw_cdev_send_stream_packet)
|
||||
|
||||
/* available since kernel version 2.6.34 */
|
||||
#define FW_CDEV_IOC_GET_CYCLE_TIMER2 _IOWR('#', 0x14, struct fw_cdev_get_cycle_timer2)
|
||||
|
||||
/*
|
||||
* FW_CDEV_VERSION History
|
||||
* 1 (2.6.22) - initial version
|
||||
@ -544,20 +547,40 @@ struct fw_cdev_stop_iso {
|
||||
/**
|
||||
* struct fw_cdev_get_cycle_timer - read cycle timer register
|
||||
* @local_time: system time, in microseconds since the Epoch
|
||||
* @cycle_timer: isochronous cycle timer, as per OHCI 1.1 clause 5.13
|
||||
* @cycle_timer: Cycle Time register contents
|
||||
*
|
||||
* The %FW_CDEV_IOC_GET_CYCLE_TIMER ioctl reads the isochronous cycle timer
|
||||
* and also the system clock. This allows to express the receive time of an
|
||||
* isochronous packet as a system time with microsecond accuracy.
|
||||
* and also the system clock (%CLOCK_REALTIME). This allows to express the
|
||||
* receive time of an isochronous packet as a system time.
|
||||
*
|
||||
* @cycle_timer consists of 7 bits cycleSeconds, 13 bits cycleCount, and
|
||||
* 12 bits cycleOffset, in host byte order.
|
||||
* 12 bits cycleOffset, in host byte order. Cf. the Cycle Time register
|
||||
* per IEEE 1394 or Isochronous Cycle Timer register per OHCI-1394.
|
||||
*/
|
||||
struct fw_cdev_get_cycle_timer {
|
||||
__u64 local_time;
|
||||
__u32 cycle_timer;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct fw_cdev_get_cycle_timer2 - read cycle timer register
|
||||
* @tv_sec: system time, seconds
|
||||
* @tv_nsec: system time, sub-seconds part in nanoseconds
|
||||
* @clk_id: input parameter, clock from which to get the system time
|
||||
* @cycle_timer: Cycle Time register contents
|
||||
*
|
||||
* The %FW_CDEV_IOC_GET_CYCLE_TIMER2 works like
|
||||
* %FW_CDEV_IOC_GET_CYCLE_TIMER but lets you choose a clock like with POSIX'
|
||||
* clock_gettime function. Supported @clk_id values are POSIX' %CLOCK_REALTIME
|
||||
* and %CLOCK_MONOTONIC and Linux' %CLOCK_MONOTONIC_RAW.
|
||||
*/
|
||||
struct fw_cdev_get_cycle_timer2 {
|
||||
__s64 tv_sec;
|
||||
__s32 tv_nsec;
|
||||
__s32 clk_id;
|
||||
__u32 cycle_timer;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct fw_cdev_allocate_iso_resource - (De)allocate a channel or bandwidth
|
||||
* @closure: Passed back to userspace in correponding iso resource events
|
||||
|
Loading…
Reference in New Issue
Block a user