aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Richter <stefanr@s5r6.in-berlin.de>2010-02-20 06:13:49 -0500
committerStefan Richter <stefanr@s5r6.in-berlin.de>2010-02-24 14:36:54 -0500
commitabfe5a01ef1e463cbafdae461b693db34e308c02 (patch)
treee33056c7d8b80a3128f7714c31b083091be3ea9b
parentfd6e0c518121d22b50060d26c8aec2b701c6aab7 (diff)
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>
-rw-r--r--drivers/firewire/core-cdev.c38
-rw-r--r--include/linux/firewire-cdev.h31
2 files changed, 59 insertions, 10 deletions
diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c
index 3c1ac0933d24..a4aa477b9b2c 100644
--- a/drivers/firewire/core-cdev.c
+++ b/drivers/firewire/core-cdev.c
@@ -1031,22 +1031,46 @@ static int ioctl_stop_iso(struct client *client, void *buffer)
1031 return fw_iso_context_stop(client->iso_context); 1031 return fw_iso_context_stop(client->iso_context);
1032} 1032}
1033 1033
1034static int ioctl_get_cycle_timer(struct client *client, void *buffer) 1034static int ioctl_get_cycle_timer2(struct client *client, void *buffer)
1035{ 1035{
1036 struct fw_cdev_get_cycle_timer *request = buffer; 1036 struct fw_cdev_get_cycle_timer2 *request = buffer;
1037 struct fw_card *card = client->device->card; 1037 struct fw_card *card = client->device->card;
1038 struct timeval tv; 1038 struct timespec ts = {0, 0};
1039 u32 cycle_time; 1039 u32 cycle_time;
1040 int ret = 0;
1040 1041
1041 local_irq_disable(); 1042 local_irq_disable();
1042 1043
1043 cycle_time = card->driver->get_cycle_time(card); 1044 cycle_time = card->driver->get_cycle_time(card);
1044 do_gettimeofday(&tv); 1045
1046 switch (request->clk_id) {
1047 case CLOCK_REALTIME: getnstimeofday(&ts); break;
1048 case CLOCK_MONOTONIC: do_posix_clock_monotonic_gettime(&ts); break;
1049 case CLOCK_MONOTONIC_RAW: getrawmonotonic(&ts); break;
1050 default:
1051 ret = -EINVAL;
1052 }
1045 1053
1046 local_irq_enable(); 1054 local_irq_enable();
1047 1055
1048 request->local_time = tv.tv_sec * 1000000ULL + tv.tv_usec; 1056 request->tv_sec = ts.tv_sec;
1049 request->cycle_timer = cycle_time; 1057 request->tv_nsec = ts.tv_nsec;
1058 request->cycle_timer = cycle_time;
1059
1060 return ret;
1061}
1062
1063static int ioctl_get_cycle_timer(struct client *client, void *buffer)
1064{
1065 struct fw_cdev_get_cycle_timer *request = buffer;
1066 struct fw_cdev_get_cycle_timer2 ct2;
1067
1068 ct2.clk_id = CLOCK_REALTIME;
1069 ioctl_get_cycle_timer2(client, &ct2);
1070
1071 request->local_time = ct2.tv_sec * USEC_PER_SEC +
1072 ct2.tv_nsec / NSEC_PER_USEC;
1073 request->cycle_timer = ct2.cycle_timer;
1050 1074
1051 return 0; 1075 return 0;
1052} 1076}
@@ -1320,6 +1344,7 @@ static int (* const ioctl_handlers[])(struct client *client, void *buffer) = {
1320 ioctl_get_speed, 1344 ioctl_get_speed,
1321 ioctl_send_broadcast_request, 1345 ioctl_send_broadcast_request,
1322 ioctl_send_stream_packet, 1346 ioctl_send_stream_packet,
1347 ioctl_get_cycle_timer2,
1323}; 1348};
1324 1349
1325static int dispatch_ioctl(struct client *client, 1350static int dispatch_ioctl(struct client *client,
@@ -1341,6 +1366,7 @@ static int dispatch_ioctl(struct client *client,
1341 struct fw_cdev_get_cycle_timer _0c; 1366 struct fw_cdev_get_cycle_timer _0c;
1342 struct fw_cdev_allocate_iso_resource _0d; 1367 struct fw_cdev_allocate_iso_resource _0d;
1343 struct fw_cdev_send_stream_packet _13; 1368 struct fw_cdev_send_stream_packet _13;
1369 struct fw_cdev_get_cycle_timer2 _14;
1344 })]; 1370 })];
1345 int ret; 1371 int ret;
1346 1372
diff --git a/include/linux/firewire-cdev.h b/include/linux/firewire-cdev.h
index 520ecf86cbb3..baa8290c8416 100644
--- a/include/linux/firewire-cdev.h
+++ b/include/linux/firewire-cdev.h
@@ -248,6 +248,9 @@ union fw_cdev_event {
248#define FW_CDEV_IOC_SEND_BROADCAST_REQUEST _IOW('#', 0x12, struct fw_cdev_send_request) 248#define FW_CDEV_IOC_SEND_BROADCAST_REQUEST _IOW('#', 0x12, struct fw_cdev_send_request)
249#define FW_CDEV_IOC_SEND_STREAM_PACKET _IOW('#', 0x13, struct fw_cdev_send_stream_packet) 249#define FW_CDEV_IOC_SEND_STREAM_PACKET _IOW('#', 0x13, struct fw_cdev_send_stream_packet)
250 250
251/* available since kernel version 2.6.34 */
252#define FW_CDEV_IOC_GET_CYCLE_TIMER2 _IOWR('#', 0x14, struct fw_cdev_get_cycle_timer2)
253
251/* 254/*
252 * FW_CDEV_VERSION History 255 * FW_CDEV_VERSION History
253 * 1 (2.6.22) - initial version 256 * 1 (2.6.22) - initial version
@@ -544,14 +547,15 @@ struct fw_cdev_stop_iso {
544/** 547/**
545 * struct fw_cdev_get_cycle_timer - read cycle timer register 548 * struct fw_cdev_get_cycle_timer - read cycle timer register
546 * @local_time: system time, in microseconds since the Epoch 549 * @local_time: system time, in microseconds since the Epoch
547 * @cycle_timer: isochronous cycle timer, as per OHCI 1.1 clause 5.13 550 * @cycle_timer: Cycle Time register contents
548 * 551 *
549 * The %FW_CDEV_IOC_GET_CYCLE_TIMER ioctl reads the isochronous cycle timer 552 * The %FW_CDEV_IOC_GET_CYCLE_TIMER ioctl reads the isochronous cycle timer
550 * and also the system clock. This allows to express the receive time of an 553 * and also the system clock (%CLOCK_REALTIME). This allows to express the
551 * isochronous packet as a system time with microsecond accuracy. 554 * receive time of an isochronous packet as a system time.
552 * 555 *
553 * @cycle_timer consists of 7 bits cycleSeconds, 13 bits cycleCount, and 556 * @cycle_timer consists of 7 bits cycleSeconds, 13 bits cycleCount, and
554 * 12 bits cycleOffset, in host byte order. 557 * 12 bits cycleOffset, in host byte order. Cf. the Cycle Time register
558 * per IEEE 1394 or Isochronous Cycle Timer register per OHCI-1394.
555 */ 559 */
556struct fw_cdev_get_cycle_timer { 560struct fw_cdev_get_cycle_timer {
557 __u64 local_time; 561 __u64 local_time;
@@ -559,6 +563,25 @@ struct fw_cdev_get_cycle_timer {
559}; 563};
560 564
561/** 565/**
566 * struct fw_cdev_get_cycle_timer2 - read cycle timer register
567 * @tv_sec: system time, seconds
568 * @tv_nsec: system time, sub-seconds part in nanoseconds
569 * @clk_id: input parameter, clock from which to get the system time
570 * @cycle_timer: Cycle Time register contents
571 *
572 * The %FW_CDEV_IOC_GET_CYCLE_TIMER2 works like
573 * %FW_CDEV_IOC_GET_CYCLE_TIMER but lets you choose a clock like with POSIX'
574 * clock_gettime function. Supported @clk_id values are POSIX' %CLOCK_REALTIME
575 * and %CLOCK_MONOTONIC and Linux' %CLOCK_MONOTONIC_RAW.
576 */
577struct fw_cdev_get_cycle_timer2 {
578 __s64 tv_sec;
579 __s32 tv_nsec;
580 __s32 clk_id;
581 __u32 cycle_timer;
582};
583
584/**
562 * struct fw_cdev_allocate_iso_resource - (De)allocate a channel or bandwidth 585 * struct fw_cdev_allocate_iso_resource - (De)allocate a channel or bandwidth
563 * @closure: Passed back to userspace in correponding iso resource events 586 * @closure: Passed back to userspace in correponding iso resource events
564 * @channels: Isochronous channels of which one is to be (de)allocated 587 * @channels: Isochronous channels of which one is to be (de)allocated