All of lore.kernel.org
 help / color / mirror / Atom feed
From: Rodolfo Giometti <giometti@enneenne.com>
To: Andrew Morton <akpm@linux-foundation.org>
Cc: linux-kernel@vger.kernel.org, dwmw2@infradead.org,
	davej@redhat.com, sam@ravnborg.org, greg@kroah.com,
	randy.dunlap@oracle.com
Subject: Re: [PATCH 1/7] LinuxPPS core support.
Date: Tue, 1 Apr 2008 23:45:22 +0200	[thread overview]
Message-ID: <20080401214522.GL7279@enneenne.com> (raw)
In-Reply-To: <20080401015555.f267d970.akpm@linux-foundation.org>

On Tue, Apr 01, 2008 at 01:55:55AM -0700, Andrew Morton wrote:
> 
> This can all be handled with suitable locking and refcounting.  The device
> which is delivering PPS interrupts has a reference on the PPS data
> structures.  If userspace has PPS open then it also has a reference.
> 
> The thread of control which releases the last reference to the PPS data
> structures also frees them all up.  This may require a schedule_work() if
> we need to support release-from-interrupt (as it appears that we do), but
> that's OK - we just need to be able to make the PPS data structures
> ineligible for new lookups while the schedule_work() is pending.
> 
> There should be no need for any thread of control to wait for any other thread
> of control to do anything.  Get the refcounting right and everything
> can be done synchronously.

Here my solution by using get/put functions:

diff --git a/drivers/pps/kapi.c b/drivers/pps/kapi.c
index d75c8c8..61c1569 100644
--- a/drivers/pps/kapi.c
+++ b/drivers/pps/kapi.c
@@ -59,6 +59,62 @@ static void pps_add_offset(struct pps_ktime *ts, struct pps_ktime *offset)
  * Exported functions
  */
 
+/* pps_get_source - find a PPS source
+ *
+ * 	source: the PPS source ID.
+ *
+ * This function is used to find an already registered PPS source into the
+ * system.
+ *
+ * The function returns NULL if found nothing, otherwise it returns a pointer
+ * to the PPS source data struct (the refcounter is incremented by 1).
+ */
+
+struct pps_device *pps_get_source(int source)
+{
+	struct pps_device *pps;
+	unsigned long flags;
+
+	spin_lock_irqsave(&pps_idr_lock, flags);
+
+	pps = idr_find(&pps_idr, source);
+	if (pps != NULL)
+		atomic_inc(&pps->usage);
+
+	spin_unlock_irqrestore(&pps_idr_lock, flags);
+
+	return pps;
+}
+
+/* pps_put_source - free the PPS source data
+ *
+ *	pps: a pointer to the PPS source.
+ *
+ * This function is used to free a PPS data struct if its refcount is 0.
+ */
+
+void pps_put_source(struct pps_device *pps)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&pps_idr_lock, flags);
+
+        BUG_ON(atomic_read(&pps->usage) == 0);
+
+	if (!atomic_dec_and_test(&pps->usage))
+		goto exit;
+
+	/* No more reference to the PPS source. We can safely remove the
+	 * PPS data struct.
+	 */
+	idr_remove(&pps_idr, pps->id);
+
+	kfree(pps);
+
+exit:
+	spin_unlock_irqrestore(&pps_idr_lock, flags);
+}
+
 /* pps_register_source - add a PPS source in the system
  *
  *	info: the PPS info struct
@@ -133,8 +189,7 @@ int pps_register_source(struct pps_source_info *info, int default_params)
 
 	init_waitqueue_head(&pps->queue);
 	spin_lock_init(&pps->lock);
-	atomic_set(&pps->usage, 0);
-	init_waitqueue_head(&pps->usage_queue);
+	atomic_set(&pps->usage, 1);
 
 	/* Create the char device */
 	err = pps_register_cdev(pps);
@@ -179,21 +234,14 @@ void pps_unregister_source(int source)
 	pps = idr_find(&pps_idr, source);
 
 	if (!pps) {
+		BUG();
 		spin_unlock_irq(&pps_idr_lock);
 		return;
 	}
-
-	/* This should be done first in order to deny IRQ handlers
-	 * to access PPS structs
-	 */
-
-	idr_remove(&pps_idr, pps->id);
 	spin_unlock_irq(&pps_idr_lock);
 
-	wait_event(pps->usage_queue, atomic_read(&pps->usage) == 0);
-
 	pps_unregister_cdev(pps);
-	kfree(pps);
+	pps_put_source(pps);
 }
 EXPORT_SYMBOL(pps_unregister_source);
 
@@ -231,16 +279,7 @@ void pps_event(int source, int event, void *data)
 		return;
 	}
 
-	spin_lock_irqsave(&pps_idr_lock, flags);
-	pps = idr_find(&pps_idr, source);
-
-	/* If we find a valid PPS source we lock it before leaving
-	 * the lock!
-	 */
-	if (pps)
-		atomic_inc(&pps->usage);
-	spin_unlock_irqrestore(&pps_idr_lock, flags);
-
+	pps = pps_get_source(source);
 	if (!pps)
 		return;
 
@@ -286,9 +325,6 @@ void pps_event(int source, int event, void *data)
 	spin_unlock_irqrestore(&pps->lock, flags);
 
 	/* Now we can release the PPS source for (possible) deregistration */
-	spin_lock_irqsave(&pps_idr_lock, flags);
-	atomic_dec(&pps->usage);
-	wake_up_all(&pps->usage_queue);
-	spin_unlock_irqrestore(&pps_idr_lock, flags);
+	pps_put_source(pps);
 }
 EXPORT_SYMBOL(pps_event);
diff --git a/drivers/pps/pps.c b/drivers/pps/pps.c
index 5cbfeb9..a46f8f4 100644
--- a/drivers/pps/pps.c
+++ b/drivers/pps/pps.c
@@ -214,15 +214,7 @@ static int pps_cdev_open(struct inode *inode, struct file *file)
 						struct pps_device, cdev);
 	int found;
 
-	spin_lock_irq(&pps_idr_lock);
-	found = idr_find(&pps_idr, pps->id) != NULL;
-
-	/* Lock the PPS source against (possible) deregistration */
-	if (found)
-		atomic_inc(&pps->usage);
-
-	spin_unlock_irq(&pps_idr_lock);
-
+	found = pps_get_source(pps->id) != 0;
 	if (!found)
 		return -ENODEV;
 
@@ -236,8 +228,7 @@ static int pps_cdev_release(struct inode *inode, struct file *file)
 	struct pps_device *pps = file->private_data;
 
 	/* Free the PPS source and wake up (possible) deregistration */
-	atomic_dec(&pps->usage);
-	wake_up_all(&pps->usage_queue);
+	pps_put_source(pps);
 
 	return 0;
 }
diff --git a/include/linux/pps.h b/include/linux/pps.h
index aca0e77..e23aaa6 100644
--- a/include/linux/pps.h
+++ b/include/linux/pps.h
@@ -173,7 +173,6 @@ struct pps_device {
 	spinlock_t lock;
 
 	atomic_t usage;				/* usage count */
-	wait_queue_head_t usage_queue;
 };
 
 /*
@@ -189,6 +188,8 @@ extern struct device_attribute pps_attrs[];
  * Exported functions
  */
 
+struct pps_device *pps_get_source(int source);
+extern void pps_put_source(struct pps_device *pps);
 extern int pps_register_source(struct pps_source_info *info,
 				int default_params);
 extern void pps_unregister_source(int source);


I'll send a new patchset ASAP!

Rodolfo

-- 

GNU/Linux Solutions                  e-mail:    giometti@enneenne.com
Linux Device Driver                             giometti@gnudd.com
Embedded Systems                     		giometti@linux.it
UNIX programming                     phone:     +39 349 2432127

  parent reply	other threads:[~2008-04-01 21:45 UTC|newest]

Thread overview: 37+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-03-06 12:08 LinuxPPS (RESUBMIT 2): the PPS Linux implementation Rodolfo Giometti
2008-03-06 12:09 ` [PATCH 1/7] LinuxPPS core support Rodolfo Giometti
2008-03-06 12:09   ` [PATCH 2/7] PPS: userland header file for PPS API Rodolfo Giometti
2008-03-06 12:09     ` [PATCH 3/7] PPS: documentation programs and examples Rodolfo Giometti
2008-03-06 12:09       ` [PATCH 4/7] PPS: LinuxPPS clients support Rodolfo Giometti
2008-03-06 12:09         ` [PATCH 5/7] PPS: serial " Rodolfo Giometti
2008-03-06 12:09           ` [PATCH 6/7] PPS: example program to enable PPS support on serial ports Rodolfo Giometti
2008-03-06 12:09             ` [PATCH 7/7] PPS: parallel port clients support Rodolfo Giometti
2008-03-20 20:04           ` [PATCH 5/7] PPS: serial " Andrew Morton
2008-03-21 11:17             ` Rodolfo Giometti
2008-03-21 17:41               ` Andrew Morton
2008-03-25 10:38                 ` Rodolfo Giometti
2008-03-20 20:03   ` [PATCH 1/7] LinuxPPS core support Andrew Morton
2008-03-25 14:44     ` Rodolfo Giometti
2008-03-28  3:25       ` Andrew Morton
2008-04-01  8:42         ` Rodolfo Giometti
2008-04-01  8:55           ` Andrew Morton
2008-04-01  9:50             ` Rodolfo Giometti
2008-04-01 21:45             ` Rodolfo Giometti [this message]
2008-04-01 21:57               ` Andrew Morton
2008-03-21  3:36   ` Kay Sievers
2008-03-21 10:56     ` Rodolfo Giometti
2008-03-21 17:00       ` Kay Sievers
2008-03-25 10:48         ` Rodolfo Giometti
2008-03-21  3:50   ` Kay Sievers
2008-03-21 10:57     ` Rodolfo Giometti
2008-03-21 17:01       ` Kay Sievers
2008-03-25 10:53     ` Rodolfo Giometti
2008-03-28 10:21   ` Andrew Morton
2008-04-01  8:59     ` Rodolfo Giometti
2008-04-01  9:09       ` Andrew Morton
2008-04-01  9:40         ` Rodolfo Giometti
2008-03-19 17:29 ` LinuxPPS (RESUBMIT 2): the PPS Linux implementation john stultz
2008-03-19 21:21   ` Andrew Morton
2008-03-19 21:55     ` Dave Jones
  -- strict thread matches above, loose matches on Subject: below --
2008-04-10 15:15 LinuxPPS (RESUBMIT 3): " Rodolfo Giometti
2008-04-10 15:15 ` [PATCH 1/7] LinuxPPS core support Rodolfo Giometti
2008-04-10 16:06 [PATCH 5/7] PPS: serial clients support Rodolfo Giometti
2008-04-10 18:22 ` LinuxPPS (RESUBMIT 4): the PPS Linux implementation Rodolfo Giometti
2008-04-10 18:22   ` [PATCH 1/7] LinuxPPS core support Rodolfo Giometti

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20080401214522.GL7279@enneenne.com \
    --to=giometti@enneenne.com \
    --cc=akpm@linux-foundation.org \
    --cc=davej@redhat.com \
    --cc=dwmw2@infradead.org \
    --cc=greg@kroah.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=randy.dunlap@oracle.com \
    --cc=sam@ravnborg.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.