patch-2.4.20 linux-2.4.20/drivers/ieee1394/ieee1394_core.c

Next file: linux-2.4.20/drivers/ieee1394/ieee1394_core.h
Previous file: linux-2.4.20/drivers/ieee1394/hosts.h
Back to the patch index
Back to the overall index

diff -urN linux-2.4.19/drivers/ieee1394/ieee1394_core.c linux-2.4.20/drivers/ieee1394/ieee1394_core.c
@@ -19,10 +19,10 @@
 #include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/proc_fs.h>
+#include <linux/tqueue.h>
 #include <asm/bitops.h>
 #include <asm/byteorder.h>
 #include <asm/semaphore.h>
-#include <asm/smplock.h>
 
 #include "ieee1394_types.h"
 #include "ieee1394.h"
@@ -67,6 +67,29 @@
         printk("\n");
 }
 
+static void process_complete_tasks(struct hpsb_packet *packet)
+{
+	struct list_head *lh, *next;
+
+	list_for_each_safe(lh, next, &packet->complete_tq) {
+		struct tq_struct *tq = list_entry(lh, struct tq_struct, list);
+		list_del(&tq->list);
+		schedule_task(tq);
+	}
+
+	return;
+}
+
+/**
+ * hpsb_add_packet_complete_task - add a new task for when a packet completes
+ * @packet: the packet whose completion we want the task added to
+ * @tq: the tq_struct describing the task to add
+ */
+void hpsb_add_packet_complete_task(struct hpsb_packet *packet, struct tq_struct *tq)
+{
+	list_add_tail(&tq->list, &packet->complete_tq);
+	return;
+}
 
 /**
  * alloc_hpsb_packet - allocate new packet structure
@@ -142,7 +165,7 @@
 int hpsb_reset_bus(struct hpsb_host *host, int type)
 {
         if (!host->in_bus_reset) {
-                host->ops->devctl(host, RESET_BUS, type);
+                host->driver->devctl(host, RESET_BUS, type);
                 return 0;
         } else {
                 return 1;
@@ -161,7 +184,10 @@
         abort_requests(host);
         host->in_bus_reset = 1;
         host->irm_id = -1;
+	host->is_irm = 0;
         host->busmgr_id = -1;
+	host->is_busmgr = 0;
+	host->is_cycmst = 0;
         host->node_count = 0;
         host->selfid_count = 0;
 
@@ -355,7 +381,10 @@
         }
 
         host->reset_retries = 0;
-        if (isroot) host->ops->devctl(host, ACT_CYCLE_MASTER, 1);
+        if (isroot) {
+		host->driver->devctl(host, ACT_CYCLE_MASTER, 1);
+		host->is_cycmst = 1;
+	}
 	atomic_inc(&host->generation);
 	host->in_bus_reset = 0;
         highlevel_host_reset(host);
@@ -379,7 +408,7 @@
                 packet->state = hpsb_complete;
                 up(&packet->state_change);
                 up(&packet->state_change);
-                run_task_queue(&packet->complete_tq);
+                process_complete_tasks(packet);
                 return;
         }
 
@@ -391,7 +420,7 @@
         spin_unlock_irqrestore(&host->pending_pkt_lock, flags);
 
         up(&packet->state_change);
-        queue_task(&host->timeout_tq, &tq_timer);
+        schedule_task(&host->timeout_tq);
 }
 
 /**
@@ -441,7 +470,7 @@
         }
 #endif
 
-        return host->ops->transmit_packet(host, packet);
+        return host->driver->transmit_packet(host, packet);
 }
 
 static void send_packet_nocare(struct hpsb_packet *packet)
@@ -529,7 +558,7 @@
 
         packet->state = hpsb_complete;
         up(&packet->state_change);
-        run_task_queue(&packet->complete_tq);
+	process_complete_tasks(packet);
 }
 
 
@@ -737,7 +766,7 @@
         struct list_head *lh;
         LIST_HEAD(llist);
 
-        host->ops->devctl(host, CANCEL_REQUESTS, 0);
+        host->driver->devctl(host, CANCEL_REQUESTS, 0);
 
         spin_lock_irqsave(&host->pending_pkt_lock, flags);
         list_splice(&host->pending_packets, &llist);
@@ -749,7 +778,7 @@
                 packet->state = hpsb_complete;
                 packet->ack_code = ACKX_ABORTED;
                 up(&packet->state_change);
-                run_task_queue(&packet->complete_tq);
+		process_complete_tasks(packet);
         }
 }
 
@@ -781,9 +810,9 @@
                 }
         }
 
-        if (!list_empty(&host->pending_packets)) {
-                queue_task(&host->timeout_tq, &tq_timer);
-        }
+        if (!list_empty(&host->pending_packets))
+		schedule_task(&host->timeout_tq);
+
         spin_unlock_irqrestore(&host->pending_pkt_lock, flags);
 
         list_for_each(lh, &expiredlist) {
@@ -791,7 +820,7 @@
                 packet->state = hpsb_complete;
                 packet->ack_code = ACKX_TIMEOUT;
                 up(&packet->state_change);
-                run_task_queue(&packet->complete_tq);
+		process_complete_tasks(packet);
         }
 }
 
@@ -862,19 +891,57 @@
 	write_unlock(&ieee1394_chardevs_lock);
 }
 
+/*
+  ieee1394_get_chardev() - look up and acquire a character device
+  driver that has previously registered using ieee1394_register_chardev()
+  
+  On success, returns 1 and sets module and file_ops to the driver.
+  The module will have an incremented reference count.
+   
+  On failure, returns 0.
+  The module will NOT have an incremented reference count.
+*/
+
+static int ieee1394_get_chardev(int blocknum,
+				struct module **module,
+				struct file_operations **file_ops)
+{
+	int ret = 0;
+       
+	if( (blocknum < 0) || (blocknum > 15) )
+		return ret;
+
+	read_lock(&ieee1394_chardevs_lock);
+
+	*module = ieee1394_chardevs[blocknum].module;
+	*file_ops = ieee1394_chardevs[blocknum].file_ops;
+
+	if(*file_ops == NULL)
+		goto out;
+
+	/* don't need try_inc_mod_count if the driver is non-modular */
+	if(*module && (try_inc_mod_count(*module) == 0))
+		goto out;
+
+	/* success! */
+	ret = 1;
+	
+out:
+	read_unlock(&ieee1394_chardevs_lock);
+	return ret;
+}
+
 /* the point of entry for open() on any ieee1394 character device */
 static int ieee1394_dispatch_open(struct inode *inode, struct file *file)
 {
 	struct file_operations *file_ops;
 	struct module *module;
 	int blocknum;
-	int retval = -ENODEV;
+	int retval;
 
 	/*
 	  Maintaining correct module reference counts is tricky here!
 
-	  For Linux v2.4 and later:
-	  
 	  The key thing to remember is that the VFS increments the
 	  reference count of ieee1394 before it calls
 	  ieee1394_dispatch_open().
@@ -887,16 +954,7 @@
 	  If the open() fails, then the VFS will drop the
 	  reference count of whatever module file->f_op->owner points
 	  to, immediately after this function returns.
-
-	  The comments below refer to the 2.4 case, since the 2.2
-	  case is trivial.
-	  
 	*/
-
-#define INCREF(mod_) do { struct module *mod = (struct module*) mod_; \
-                          if(mod != NULL) __MOD_INC_USE_COUNT(mod); } while(0)
-#define DECREF(mod_) do { struct module *mod = (struct module*) mod_; \
-                          if(mod != NULL) __MOD_DEC_USE_COUNT(mod); } while(0)
 	
         /* shift away lower four bits of the minor
 	   to get the index of the ieee1394_driver
@@ -904,20 +962,10 @@
 	
 	blocknum = (minor(inode->i_rdev) >> 4) & 0xF;
 
-	/* printk("ieee1394_dispatch_open(%d)", blocknum); */
+	/* look up the driver */
 
-	read_lock(&ieee1394_chardevs_lock);
-	module = ieee1394_chardevs[blocknum].module;
-	/* bump the reference count of the driver that
-	   will receive the open() */
-	INCREF(module);
-	file_ops = ieee1394_chardevs[blocknum].file_ops;
-	read_unlock(&ieee1394_chardevs_lock);
-
-	if(file_ops == NULL) {
-		DECREF(module);
-		goto out_fail;
-	}
+	if(ieee1394_get_chardev(blocknum, &module, &file_ops) == 0)
+		return -ENODEV;
 
 	/* redirect all subsequent requests to the driver's
 	   own file_operations */
@@ -929,42 +977,42 @@
 	/* follow through with the open() */
 	retval = file_ops->open(inode, file);
 
-	if(retval) {
+	if(retval == 0) {
 		
-		/* if the open() failed, then we need to drop the
-                   extra reference we gave to the task-specific
-                   driver */
+		/* If the open() succeeded, then ieee1394 will be left
+		   with an extra module reference, so we discard it here.
 
-		DECREF(module);
-		goto out_fail;
+		   The task-specific driver still has the extra
+		   reference given to it by ieee1394_get_chardev().
+		   This extra reference prevents the module from
+		   unloading while the file is open, and will be
+		   dropped by the VFS when the file is released.
+		*/
 		
-	} else {
-
-		/* if the open() succeeded, then ieee1394 will be left
-		   with an extra module reference, so we discard it here.*/
+		if(THIS_MODULE)
+			__MOD_DEC_USE_COUNT((struct module*) THIS_MODULE);
+		
+		/* note that if ieee1394 is compiled into the kernel,
+		   THIS_MODULE will be (void*) NULL, hence the if and
+		   the cast are necessary */
 
-		DECREF(THIS_MODULE);
+	} else {
 
-		/* the task-specific driver still has the extra
-		   reference we gave it. This extra reference prevents
-		   the module from unloading while the file is open,
-		   and will be dropped by the VFS when the file is
-		   released. */
+		/* if the open() failed, then we need to drop the
+		   extra reference we gave to the task-specific
+		   driver */
 		
-		return 0;
-	}
-	       
-out_fail:
-	/* point the file's f_ops back to ieee1394. The VFS will then
-	   decrement ieee1394's reference count immediately after this
-	   function returns. */
+		if(module)
+			__MOD_DEC_USE_COUNT(module);
 	
-	file->f_op = &ieee1394_chardev_ops;
-	return retval;
+		/* point the file's f_ops back to ieee1394. The VFS will then
+		   decrement ieee1394's reference count immediately after this
+		   function returns. */
+		
+		file->f_op = &ieee1394_chardev_ops;
+	}
 
-#undef INCREF
-#undef DECREF
-	     
+	return retval;
 }
 
 struct proc_dir_entry *ieee1394_procfs_entry;
@@ -1025,14 +1073,13 @@
 module_exit(ieee1394_cleanup);
 
 /* Exported symbols */
-EXPORT_SYMBOL(hpsb_register_lowlevel);
-EXPORT_SYMBOL(hpsb_unregister_lowlevel);
 EXPORT_SYMBOL(hpsb_alloc_host);
 EXPORT_SYMBOL(hpsb_add_host);
 EXPORT_SYMBOL(hpsb_remove_host);
 EXPORT_SYMBOL(hpsb_ref_host);
 EXPORT_SYMBOL(hpsb_unref_host);
 EXPORT_SYMBOL(hpsb_speedto_str);
+EXPORT_SYMBOL(hpsb_add_packet_complete_task);
 
 EXPORT_SYMBOL(alloc_hpsb_packet);
 EXPORT_SYMBOL(free_hpsb_packet);

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