patch-2.4.0-test3 linux/drivers/ieee1394/ieee1394_transactions.c

Next file: linux/drivers/ieee1394/ieee1394_types.h
Previous file: linux/drivers/ieee1394/ieee1394_syms.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.0-test2/linux/drivers/ieee1394/ieee1394_transactions.c linux/drivers/ieee1394/ieee1394_transactions.c
@@ -4,6 +4,9 @@
  * Transaction support.
  *
  * Copyright (C) 1999 Andreas E. Bombe
+ *
+ * This code is licensed under the GPL.  See the file COPYING in the root
+ * directory of the kernel sources for details.
  */
 
 #include <linux/sched.h>
@@ -152,38 +155,58 @@
  * Return value: The allocated transaction label or -1 if there was no free
  * tlabel and @wait is false.
  */
+static int __get_tlabel(struct hpsb_host *host, nodeid_t nodeid)
+{
+	int tlabel;
+
+	if (host->tlabel_count) {
+		host->tlabel_count--;
+
+		if (host->tlabel_pool[0] != ~0) {
+			tlabel = ffz(host->tlabel_pool[0]);
+			host->tlabel_pool[0] |= 1 << tlabel;
+		} else {
+			tlabel = ffz(host->tlabel_pool[1]);
+			host->tlabel_pool[1] |= 1 << tlabel;
+			tlabel += 32;
+		}
+		return tlabel;
+	}
+	return -1;	
+}
+
 int get_tlabel(struct hpsb_host *host, nodeid_t nodeid, int wait)
 {
         unsigned long flags;
         int tlabel;
+	wait_queue_t wq;
 
-        while (1) {
-                spin_lock_irqsave(&host->tlabel_lock, flags);
+	spin_lock_irqsave(&host->tlabel_lock, flags);
 
-                if (host->tlabel_count) {
-                        host->tlabel_count--;
+        tlabel = __get_tlabel(host, nodeid);
+	if (tlabel != -1 || !wait) {
+		spin_unlock_irqrestore(&host->tlabel_lock, flags);
+		return tlabel;
+	}
+
+	init_waitqueue_entry(&wq, current);
+	add_wait_queue(&host->tlabel_wait, &wq);
+
+	for (;;) {
+                set_current_state(TASK_UNINTERRUPTIBLE);
+                tlabel = __get_tlabel(host, nodeid);
+		if (tlabel != -1) break;
+		
+		spin_unlock_irqrestore(&host->tlabel_lock, flags);
+		schedule();
+		spin_lock_irqsave(&host->tlabel_lock, flags);
+	}
+
+	spin_unlock_irqrestore(&host->tlabel_lock, flags);
+	set_current_state(TASK_RUNNING);
+	remove_wait_queue(&host->tlabel_wait, &wq);
 
-                        if (host->tlabel_pool[0] != ~0) {
-                                tlabel = ffz(host->tlabel_pool[0]);
-                                host->tlabel_pool[0] |= 1 << tlabel;
-                        } else {
-                                tlabel = ffz(host->tlabel_pool[1]);
-                                host->tlabel_pool[1] |= 1 << tlabel;
-                                tlabel += 32;
-                        }
-                
-                        spin_unlock_irqrestore(&host->tlabel_lock, flags);
-                        return tlabel;
-                }
-
-                spin_unlock_irqrestore(&host->tlabel_lock, flags);
-
-                if (wait) {
-                        sleep_on(&host->tlabel_wait);
-                } else {
-                        return -1;
-                }
-        }
+	return tlabel;
 }
 
 /**

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)