Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Pieter Palmers and committed by
Stefan Richter
3dc5ea9b 91efa462

+78
+2
drivers/ieee1394/ieee1394-ioctl.h
··· 100 100 _IO ('#', 0x28) 101 101 #define RAW1394_IOC_ISO_RECV_FLUSH \ 102 102 _IO ('#', 0x29) 103 + #define RAW1394_IOC_GET_CYCLE_TIMER \ 104 + _IOR ('#', 0x30, struct raw1394_cycle_timer) 103 105 104 106 #endif /* __IEEE1394_IOCTL_H */
+43
drivers/ieee1394/ieee1394_core.c
··· 33 33 #include <linux/skbuff.h> 34 34 #include <linux/suspend.h> 35 35 #include <linux/kthread.h> 36 + #include <linux/preempt.h> 37 + #include <linux/time.h> 36 38 39 + #include <asm/system.h> 37 40 #include <asm/byteorder.h> 38 41 39 42 #include "ieee1394_types.h" ··· 189 186 } 190 187 } 191 188 189 + /** 190 + * hpsb_read_cycle_timer - read cycle timer register and system time 191 + * @host: host whose isochronous cycle timer register is read 192 + * @cycle_timer: address of bitfield to return the register contents 193 + * @local_time: address to return the system time 194 + * 195 + * The format of * @cycle_timer, is described in OHCI 1.1 clause 5.13. This 196 + * format is also read from non-OHCI controllers. * @local_time contains the 197 + * system time in microseconds since the Epoch, read at the moment when the 198 + * cycle timer was read. 199 + * 200 + * Return value: 0 for success or error number otherwise. 201 + */ 202 + int hpsb_read_cycle_timer(struct hpsb_host *host, u32 *cycle_timer, 203 + u64 *local_time) 204 + { 205 + int ctr; 206 + struct timeval tv; 207 + unsigned long flags; 208 + 209 + if (!host || !cycle_timer || !local_time) 210 + return -EINVAL; 211 + 212 + preempt_disable(); 213 + local_irq_save(flags); 214 + 215 + ctr = host->driver->devctl(host, GET_CYCLE_COUNTER, 0); 216 + if (ctr) 217 + do_gettimeofday(&tv); 218 + 219 + local_irq_restore(flags); 220 + preempt_enable(); 221 + 222 + if (!ctr) 223 + return -EIO; 224 + *cycle_timer = ctr; 225 + *local_time = tv.tv_sec * 1000000ULL + tv.tv_usec; 226 + return 0; 227 + } 192 228 193 229 int hpsb_bus_reset(struct hpsb_host *host) 194 230 { ··· 1232 1190 EXPORT_SYMBOL(hpsb_free_packet); 1233 1191 EXPORT_SYMBOL(hpsb_send_packet); 1234 1192 EXPORT_SYMBOL(hpsb_reset_bus); 1193 + EXPORT_SYMBOL(hpsb_read_cycle_timer); 1235 1194 EXPORT_SYMBOL(hpsb_bus_reset); 1236 1195 EXPORT_SYMBOL(hpsb_selfid_received); 1237 1196 EXPORT_SYMBOL(hpsb_selfid_complete);
+3
drivers/ieee1394/ieee1394_core.h
··· 127 127 * progress, 0 otherwise. */ 128 128 int hpsb_reset_bus(struct hpsb_host *host, int type); 129 129 130 + int hpsb_read_cycle_timer(struct hpsb_host *host, u32 *cycle_timer, 131 + u64 *local_time); 132 + 130 133 /* 131 134 * The following functions are exported for host driver module usage. All of 132 135 * them are safe to use in interrupt contexts, although some are quite
+20
drivers/ieee1394/raw1394.c
··· 2669 2669 fi->iso_state = RAW1394_ISO_INACTIVE; 2670 2670 } 2671 2671 2672 + static 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 2684 /* mmap the rawiso xmit/recv buffer */ 2673 2685 static int raw1394_mmap(struct file *file, struct vm_area_struct *vma) 2674 2686 { ··· 2785 2773 return 0; 2786 2774 } 2787 2775 break; 2776 + default: 2777 + break; 2778 + } 2779 + 2780 + /* state-independent commands */ 2781 + switch(cmd) { 2782 + case RAW1394_IOC_GET_CYCLE_TIMER: 2783 + return raw1394_read_cycle_timer(fi, argp); 2788 2784 default: 2789 2785 break; 2790 2786 }
+10
drivers/ieee1394/raw1394.h
··· 178 178 __s16 xmit_cycle; 179 179 }; 180 180 181 + /* argument to RAW1394_IOC_GET_CYCLE_TIMER ioctl */ 182 + struct 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 191 #endif /* IEEE1394_RAW1394_H */