[patch] parport interface change

From: Tim Waugh (twaugh@redhat.com)
Date: Thu Jun 15 2000 - 12:38:00 EST


I didn't want to do this, but it looks like it's necessary.

I'd like to add two functions to the parport API, for reference
counting the ports.

* Don't use parport_enumerate

* Do use parport_register_driver

* In your attach(port) function, port is valid. To make it valid
  outside the attach() function, use parport_get_port, and remember to
  use parport_put_port when you're done with it (at module unload or
  whenever).

Comments?

Tim.
*/

Index: drivers/parport/share.c
===================================================================
RCS file: /usr/local/src/cvsroot/linux/drivers/parport/share.c,v
retrieving revision 1.15
diff -d -u -r1.15 share.c
--- drivers/parport/share.c 2000/06/06 13:15:55 1.15
+++ drivers/parport/share.c 2000/06/15 17:33:14
@@ -87,6 +87,7 @@
 {
         struct parport_driver *drv;
 
+ parport_get_port (port);
         spin_lock (&driverlist_lock);
         for (drv = driver_chain; drv; drv = drv->next) {
                 if (attach)
@@ -95,6 +96,7 @@
                         drv->detach (port);
         }
         spin_unlock (&driverlist_lock);
+ parport_put_port (port);
 }
 
 /* Ask kmod for some lowlevel drivers. */
@@ -196,6 +198,53 @@
         }
 }
 
+static void free_port (struct parport *port)
+{
+ int d;
+ for (d = 0; d < 5; d++) {
+ if (port->probe_info[d].class_name)
+ kfree (port->probe_info[d].class_name);
+ if (port->probe_info[d].mfr)
+ kfree (port->probe_info[d].mfr);
+ if (port->probe_info[d].model)
+ kfree (port->probe_info[d].model);
+ if (port->probe_info[d].cmdset)
+ kfree (port->probe_info[d].cmdset);
+ if (port->probe_info[d].description)
+ kfree (port->probe_info[d].description);
+ }
+
+ kfree(port->name);
+ kfree(port);
+}
+
+/**
+ * parport_get_port - increment the port's reference count
+ *
+ * This ensure's that a struct parport pointer remains valid
+ * until the matching parport_put_port() call.
+ **/
+struct parport *parport_get_port (struct parport *port)
+{
+ atomic_inc (&port->ref_count);
+ return port;
+}
+
+/**
+ * parport_put_port - decrement the port's reference count
+ *
+ * This should be called once for each call to parport_get_port(),
+ * once the port is no longer needed.
+ **/
+void parport_put_port (struct parport *port)
+{
+ if (!atomic_dec_and_test (&port->ref_count))
+ /* Can destroy it now. */
+ free_port (port);
+
+ return;
+}
+
 /**
  * parport_enumerate - return a list of the system's parallel ports
  *
@@ -298,6 +347,7 @@
         tmp->ieee1284.phase = IEEE1284_PH_FWD_IDLE;
         init_MUTEX_LOCKED (&tmp->ieee1284.irq); /* actually a semaphore at 0 */
         tmp->spintime = parport_default_spintime;
+ atomic_set (&tmp->ref_count, 0);
 
         name = kmalloc(15, GFP_KERNEL);
         if (!name) {
@@ -377,26 +427,6 @@
         call_driver_chain (1, port);
 }
 
-static void free_port (struct parport *port)
-{
- int d;
- for (d = 0; d < 5; d++) {
- if (port->probe_info[d].class_name)
- kfree (port->probe_info[d].class_name);
- if (port->probe_info[d].mfr)
- kfree (port->probe_info[d].mfr);
- if (port->probe_info[d].model)
- kfree (port->probe_info[d].model);
- if (port->probe_info[d].cmdset)
- kfree (port->probe_info[d].cmdset);
- if (port->probe_info[d].description)
- kfree (port->probe_info[d].description);
- }
-
- kfree(port->name);
- kfree(port);
-}
-
 /**
  * parport_unregister_port - deregister a parallel port
  * @port: parallel port to deregister
@@ -451,7 +481,7 @@
         spin_unlock(&parportlist_lock);
 
         /* Yes, parport_enumerate _is_ unsafe. Don't use it. */
- if (!port->devices)
+ if (!atomic_read (&port->ref_count))
                 free_port (port);
 }
 
Index: include/linux/parport.h
===================================================================
RCS file: /usr/local/src/cvsroot/linux/include/linux/parport.h,v
retrieving revision 1.7
diff -d -u -r1.7 parport.h
--- include/linux/parport.h 2000/04/06 10:22:15 1.7
+++ include/linux/parport.h 2000/06/15 17:33:14
@@ -302,6 +302,7 @@
         rwlock_t cad_lock;
 
         int spintime;
+ atomic_t ref_count;
 };
 
 #define DEFAULT_SPIN_TIME 500 /* us */
@@ -330,12 +331,9 @@
 /* Unregister a port. */
 extern void parport_unregister_port(struct parport *port);
 
-/* parport_in_use returns nonzero if there are devices attached to a
- port. */
-#define parport_in_use(x) ((x)->devices != NULL)
-
 /* parport_enumerate returns a pointer to the linked list of all the
- ports in this machine. */
+ ports in this machine. DON'T USE THIS. Use
+ parport_register_driver instead. */
 struct parport *parport_enumerate(void);
 
 /* Register a new high-level driver. */
@@ -343,6 +341,10 @@
 
 /* Unregister a high-level driver. */
 extern void parport_unregister_driver (struct parport_driver *);
+
+/* Reference counting for ports. */
+extern struct parport *parport_get_port (struct parport *);
+extern void parport_put_port (struct parport *);
 
 /* parport_register_device declares that a device is connected to a
    port, and tells the kernel all it needs to know.



-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Thu Jun 15 2000 - 21:00:35 EST