Merge branch 'for-linus' of ssh://master.kernel.org/pub/scm/linux/kernel/git/ieee1394...
authorLinus Torvalds <torvalds@woody.linux-foundation.org>
Mon, 19 Feb 2007 21:07:19 +0000 (13:07 -0800)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>
Mon, 19 Feb 2007 21:07:19 +0000 (13:07 -0800)
* 'for-linus' of ssh://master.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6:
  ieee1394: fix another deadlock in nodemgr
  ieee1394: cycle timer read extension for raw1394

drivers/ieee1394/ieee1394-ioctl.h
drivers/ieee1394/ieee1394_core.c
drivers/ieee1394/ieee1394_core.h
drivers/ieee1394/nodemgr.c
drivers/ieee1394/raw1394.c
drivers/ieee1394/raw1394.h

index 8f20750..46878fe 100644 (file)
        _IO  ('#', 0x28)
 #define RAW1394_IOC_ISO_RECV_FLUSH             \
        _IO  ('#', 0x29)
+#define RAW1394_IOC_GET_CYCLE_TIMER            \
+       _IOR ('#', 0x30, struct raw1394_cycle_timer)
 
 #endif /* __IEEE1394_IOCTL_H */
index 1521e57..d791d08 100644 (file)
 #include <linux/skbuff.h>
 #include <linux/suspend.h>
 #include <linux/kthread.h>
+#include <linux/preempt.h>
+#include <linux/time.h>
 
+#include <asm/system.h>
 #include <asm/byteorder.h>
 
 #include "ieee1394_types.h"
@@ -186,6 +189,45 @@ int hpsb_reset_bus(struct hpsb_host *host, int type)
        }
 }
 
+/**
+ * hpsb_read_cycle_timer - read cycle timer register and system time
+ * @host: host whose isochronous cycle timer register is read
+ * @cycle_timer: address of bitfield to return the register contents
+ * @local_time: address to return the system time
+ *
+ * The format of * @cycle_timer, is described in OHCI 1.1 clause 5.13. This
+ * format is also read from non-OHCI controllers. * @local_time contains the
+ * system time in microseconds since the Epoch, read at the moment when the
+ * cycle timer was read.
+ *
+ * Return value: 0 for success or error number otherwise.
+ */
+int hpsb_read_cycle_timer(struct hpsb_host *host, u32 *cycle_timer,
+                         u64 *local_time)
+{
+       int ctr;
+       struct timeval tv;
+       unsigned long flags;
+
+       if (!host || !cycle_timer || !local_time)
+               return -EINVAL;
+
+       preempt_disable();
+       local_irq_save(flags);
+
+       ctr = host->driver->devctl(host, GET_CYCLE_COUNTER, 0);
+       if (ctr)
+               do_gettimeofday(&tv);
+
+       local_irq_restore(flags);
+       preempt_enable();
+
+       if (!ctr)
+               return -EIO;
+       *cycle_timer = ctr;
+       *local_time = tv.tv_sec * 1000000ULL + tv.tv_usec;
+       return 0;
+}
 
 int hpsb_bus_reset(struct hpsb_host *host)
 {
@@ -1190,6 +1232,7 @@ EXPORT_SYMBOL(hpsb_alloc_packet);
 EXPORT_SYMBOL(hpsb_free_packet);
 EXPORT_SYMBOL(hpsb_send_packet);
 EXPORT_SYMBOL(hpsb_reset_bus);
+EXPORT_SYMBOL(hpsb_read_cycle_timer);
 EXPORT_SYMBOL(hpsb_bus_reset);
 EXPORT_SYMBOL(hpsb_selfid_received);
 EXPORT_SYMBOL(hpsb_selfid_complete);
index 536ba3f..bd29d8e 100644 (file)
@@ -127,6 +127,9 @@ int hpsb_send_packet_and_wait(struct hpsb_packet *packet);
  * progress, 0 otherwise. */
 int hpsb_reset_bus(struct hpsb_host *host, int type);
 
+int hpsb_read_cycle_timer(struct hpsb_host *host, u32 *cycle_timer,
+                         u64 *local_time);
+
 /*
  * The following functions are exported for host driver module usage.  All of
  * them are safe to use in interrupt contexts, although some are quite
index ba9faef..c5ace19 100644 (file)
@@ -1681,7 +1681,8 @@ static int nodemgr_host_thread(void *__hi)
        for (;;) {
                /* Sleep until next bus reset */
                set_current_state(TASK_INTERRUPTIBLE);
-               if (get_hpsb_generation(host) == generation)
+               if (get_hpsb_generation(host) == generation &&
+                   !kthread_should_stop())
                        schedule();
                __set_current_state(TASK_RUNNING);
 
index aa9ca83..bb897a3 100644 (file)
@@ -2669,6 +2669,18 @@ static void raw1394_iso_shutdown(struct file_info *fi)
        fi->iso_state = RAW1394_ISO_INACTIVE;
 }
 
+static int raw1394_read_cycle_timer(struct file_info *fi, void __user * uaddr)
+{
+       struct raw1394_cycle_timer ct;
+       int err;
+
+       err = hpsb_read_cycle_timer(fi->host, &ct.cycle_timer, &ct.local_time);
+       if (!err)
+               if (copy_to_user(uaddr, &ct, sizeof(ct)))
+                       err = -EFAULT;
+       return err;
+}
+
 /* mmap the rawiso xmit/recv buffer */
 static int raw1394_mmap(struct file *file, struct vm_area_struct *vma)
 {
@@ -2777,6 +2789,14 @@ static int raw1394_ioctl(struct inode *inode, struct file *file,
                break;
        }
 
+       /* state-independent commands */
+       switch(cmd) {
+       case RAW1394_IOC_GET_CYCLE_TIMER:
+               return raw1394_read_cycle_timer(fi, argp);
+       default:
+               break;
+       }
+
        return -EINVAL;
 }
 
index 35bfc38..7bd22ee 100644 (file)
@@ -178,4 +178,14 @@ struct raw1394_iso_status {
        __s16 xmit_cycle;
 };
 
+/* argument to RAW1394_IOC_GET_CYCLE_TIMER ioctl */
+struct raw1394_cycle_timer {
+       /* contents of Isochronous Cycle Timer register,
+          as in OHCI 1.1 clause 5.13 (also with non-OHCI hosts) */
+       __u32 cycle_timer;
+
+       /* local time in microseconds since Epoch,
+          simultaneously read with cycle timer */
+       __u64 local_time;
+};
 #endif /* IEEE1394_RAW1394_H */