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
- Lines: 339
- Date:
Thu Nov 28 15:53:13 2002
- Orig file:
linux-2.4.19/drivers/ieee1394/ieee1394_core.c
- Orig date:
Fri Aug 2 17:39:44 2002
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)