aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPieter Palmers <pieterp@joow.be>2007-02-03 11:44:39 -0500
committerStefan Richter <stefanr@s5r6.in-berlin.de>2007-02-17 08:39:33 -0500
commit3dc5ea9b31a8c83cffa338aba91adbc9bd387002 (patch)
tree5a9d9682d77fb3a1cfd3dc27654301f69ababf12
parent91efa462054d44ae52b0c6c8325ed5e899f2cd17 (diff)
ieee1394: cycle timer read extension for raw1394
This implements the simultaneous read of the isochronous cycle timer and the system clock (in usecs). This allows to express the exact receive time of an ISO packet as a system time with microsecond accuracy. http://bugzilla.kernel.org/show_bug.cgi?id=7773 The counterpart patch for libraw1394 can be found at http://thread.gmane.org/gmane.linux.kernel.firewire.devel/8934 Patch update (Stefan R.): Disable preemption and local interrupts. Prevent integer overflow. Add paranoid error checks and kerneldoc to hpsb_read_cycle_timer. Move it to other ieee1394_core high-level API functions. Change comments. Adjust whitespace. Rename struct _raw1394_cycle_timer. Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de> Acked-by: Pieter Palmers <pieterp@joow.be> Acked-by: Dan Dennedy <dan@dennedy.org>
-rw-r--r--drivers/ieee1394/ieee1394-ioctl.h2
-rw-r--r--drivers/ieee1394/ieee1394_core.c43
-rw-r--r--drivers/ieee1394/ieee1394_core.h3
-rw-r--r--drivers/ieee1394/raw1394.c20
-rw-r--r--drivers/ieee1394/raw1394.h10
5 files changed, 78 insertions, 0 deletions
diff --git a/drivers/ieee1394/ieee1394-ioctl.h b/drivers/ieee1394/ieee1394-ioctl.h
index 8f207508ed1d..46878fef136c 100644
--- a/drivers/ieee1394/ieee1394-ioctl.h
+++ b/drivers/ieee1394/ieee1394-ioctl.h
@@ -100,5 +100,7 @@
100 _IO ('#', 0x28) 100 _IO ('#', 0x28)
101#define RAW1394_IOC_ISO_RECV_FLUSH \ 101#define RAW1394_IOC_ISO_RECV_FLUSH \
102 _IO ('#', 0x29) 102 _IO ('#', 0x29)
103#define RAW1394_IOC_GET_CYCLE_TIMER \
104 _IOR ('#', 0x30, struct raw1394_cycle_timer)
103 105
104#endif /* __IEEE1394_IOCTL_H */ 106#endif /* __IEEE1394_IOCTL_H */
diff --git a/drivers/ieee1394/ieee1394_core.c b/drivers/ieee1394/ieee1394_core.c
index 1521e57e124b..d791d08c743c 100644
--- a/drivers/ieee1394/ieee1394_core.c
+++ b/drivers/ieee1394/ieee1394_core.c
@@ -33,7 +33,10 @@
33#include <linux/skbuff.h> 33#include <linux/skbuff.h>
34#include <linux/suspend.h> 34#include <linux/suspend.h>
35#include <linux/kthread.h> 35#include <linux/kthread.h>
36#include <linux/preempt.h>
37#include <linux/time.h>
36 38
39#include <asm/system.h>
37#include <asm/byteorder.h> 40#include <asm/byteorder.h>
38 41
39#include "ieee1394_types.h" 42#include "ieee1394_types.h"
@@ -186,6 +189,45 @@ int hpsb_reset_bus(struct hpsb_host *host, int type)
186 } 189 }
187} 190}
188 191
192/**
193 * hpsb_read_cycle_timer - read cycle timer register and system time
194 * @host: host whose isochronous cycle timer register is read
195 * @cycle_timer: address of bitfield to return the register contents
196 * @local_time: address to return the system time
197 *
198 * The format of * @cycle_timer, is described in OHCI 1.1 clause 5.13. This
199 * format is also read from non-OHCI controllers. * @local_time contains the
200 * system time in microseconds since the Epoch, read at the moment when the
201 * cycle timer was read.
202 *
203 * Return value: 0 for success or error number otherwise.
204 */
205int hpsb_read_cycle_timer(struct hpsb_host *host, u32 *cycle_timer,
206 u64 *local_time)
207{
208 int ctr;
209 struct timeval tv;
210 unsigned long flags;
211
212 if (!host || !cycle_timer || !local_time)
213 return -EINVAL;
214
215 preempt_disable();
216 local_irq_save(flags);
217
218 ctr = host->driver->devctl(host, GET_CYCLE_COUNTER, 0);
219 if (ctr)
220 do_gettimeofday(&tv);
221
222 local_irq_restore(flags);
223 preempt_enable();
224
225 if (!ctr)
226 return -EIO;
227 *cycle_timer = ctr;
228 *local_time = tv.tv_sec * 1000000ULL + tv.tv_usec;
229 return 0;
230}
189 231
190int hpsb_bus_reset(struct hpsb_host *host) 232int hpsb_bus_reset(struct hpsb_host *host)
191{ 233{
@@ -1190,6 +1232,7 @@ EXPORT_SYMBOL(hpsb_alloc_packet);
1190EXPORT_SYMBOL(hpsb_free_packet); 1232EXPORT_SYMBOL(hpsb_free_packet);
1191EXPORT_SYMBOL(hpsb_send_packet); 1233EXPORT_SYMBOL(hpsb_send_packet);
1192EXPORT_SYMBOL(hpsb_reset_bus); 1234EXPORT_SYMBOL(hpsb_reset_bus);
1235EXPORT_SYMBOL(hpsb_read_cycle_timer);
1193EXPORT_SYMBOL(hpsb_bus_reset); 1236EXPORT_SYMBOL(hpsb_bus_reset);
1194EXPORT_SYMBOL(hpsb_selfid_received); 1237EXPORT_SYMBOL(hpsb_selfid_received);
1195EXPORT_SYMBOL(hpsb_selfid_complete); 1238EXPORT_SYMBOL(hpsb_selfid_complete);
diff --git a/drivers/ieee1394/ieee1394_core.h b/drivers/ieee1394/ieee1394_core.h
index 536ba3f580fd..bd29d8ef5bbd 100644
--- a/drivers/ieee1394/ieee1394_core.h
+++ b/drivers/ieee1394/ieee1394_core.h
@@ -127,6 +127,9 @@ int hpsb_send_packet_and_wait(struct hpsb_packet *packet);
127 * progress, 0 otherwise. */ 127 * progress, 0 otherwise. */
128int hpsb_reset_bus(struct hpsb_host *host, int type); 128int hpsb_reset_bus(struct hpsb_host *host, int type);
129 129
130int hpsb_read_cycle_timer(struct hpsb_host *host, u32 *cycle_timer,
131 u64 *local_time);
132
130/* 133/*
131 * The following functions are exported for host driver module usage. All of 134 * The following functions are exported for host driver module usage. All of
132 * them are safe to use in interrupt contexts, although some are quite 135 * them are safe to use in interrupt contexts, although some are quite
diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c
index a77a832828c8..5d08d7450f96 100644
--- a/drivers/ieee1394/raw1394.c
+++ b/drivers/ieee1394/raw1394.c
@@ -2669,6 +2669,18 @@ static void raw1394_iso_shutdown(struct file_info *fi)
2669 fi->iso_state = RAW1394_ISO_INACTIVE; 2669 fi->iso_state = RAW1394_ISO_INACTIVE;
2670} 2670}
2671 2671
2672static int raw1394_read_cycle_timer(struct file_info *fi, void __user * uaddr)
2673{
2674 struct raw1394_cycle_timer ct;
2675 int err;
2676
2677 err = hpsb_read_cycle_timer(fi->host, &ct.cycle_timer, &ct.local_time);
2678 if (!err)
2679 if (copy_to_user(uaddr, &ct, sizeof(ct)))
2680 err = -EFAULT;
2681 return err;
2682}
2683
2672/* mmap the rawiso xmit/recv buffer */ 2684/* mmap the rawiso xmit/recv buffer */
2673static int raw1394_mmap(struct file *file, struct vm_area_struct *vma) 2685static int raw1394_mmap(struct file *file, struct vm_area_struct *vma)
2674{ 2686{
@@ -2777,6 +2789,14 @@ static int raw1394_ioctl(struct inode *inode, struct file *file,
2777 break; 2789 break;
2778 } 2790 }
2779 2791
2792 /* state-independent commands */
2793 switch(cmd) {
2794 case RAW1394_IOC_GET_CYCLE_TIMER:
2795 return raw1394_read_cycle_timer(fi, argp);
2796 default:
2797 break;
2798 }
2799
2780 return -EINVAL; 2800 return -EINVAL;
2781} 2801}
2782 2802
diff --git a/drivers/ieee1394/raw1394.h b/drivers/ieee1394/raw1394.h
index 35bfc38f013c..7bd22ee1afbb 100644
--- a/drivers/ieee1394/raw1394.h
+++ b/drivers/ieee1394/raw1394.h
@@ -178,4 +178,14 @@ struct raw1394_iso_status {
178 __s16 xmit_cycle; 178 __s16 xmit_cycle;
179}; 179};
180 180
181/* argument to RAW1394_IOC_GET_CYCLE_TIMER ioctl */
182struct raw1394_cycle_timer {
183 /* contents of Isochronous Cycle Timer register,
184 as in OHCI 1.1 clause 5.13 (also with non-OHCI hosts) */
185 __u32 cycle_timer;
186
187 /* local time in microseconds since Epoch,
188 simultaneously read with cycle timer */
189 __u64 local_time;
190};
181#endif /* IEEE1394_RAW1394_H */ 191#endif /* IEEE1394_RAW1394_H */