netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Stephen Hemminger <shemminger@osdl.org>
To: jt@hpl.hp.com
Cc: jt@bougret.hpl.hp.com, "David S. Miller" <davem@redhat.com>,
	irda-users@lists.sourceforge.net, netdev@oss.sgi.com
Subject: [PATCH] (1/11) Irda dongle module owner support (revised)
Date: Fri, 3 Oct 2003 10:21:33 -0700	[thread overview]
Message-ID: <20031003102133.2e5a41a2.shemminger@osdl.org> (raw)
In-Reply-To: <20031002233335.GA7945@bougret.hpl.hp.com>

Revised version of the dongle module owner patch, incorporating Jean's comments.
This replaces the original patch.  It provides an owner field an appropriate 
ref counting for IRDA dongles.

Changes since list version:
	s/dongle_lock/dongles->hb_spinlock/
	get lock on device_cleanup
	replace ASSERT() about in_interrupt with might_sleep().

In case your curious about locking, the callers are:
	module_init -> irda_device_init
	module_exit -> irda_device_cleanup
	irport_net_ioctl -> irda_device_dongle_init
	module_init -> XXX_dongle_init -> irda_device_register_dongle
	module_exit -> XXX_dongle_exit -> irda_device_unregister_dongle

In other words, no interrupt or BH access to the dongle list.
Obviously, hashing this list is overkill, but "when in Rome"...

--- linux-2.5/net/irda/irda_device.c	2003-10-01 13:40:11.000000000 -0700
+++ irda-2.5/net/irda/irda_device.c	2003-10-03 10:03:52.497879915 -0700
@@ -85,7 +85,7 @@ static void irda_task_timer_expired(void
 
 int __init irda_device_init( void)
 {
-	dongles = hashbin_new(HB_LOCK);
+	dongles = hashbin_new(HB_NOLOCK);
 	if (dongles == NULL) {
 		printk(KERN_WARNING "IrDA: Can't allocate dongles hashbin!\n");
 		return -ENOMEM;
@@ -109,7 +109,9 @@ void __exit irda_device_cleanup(void)
 	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
 
 	hashbin_delete(tasks, (FREE_FUNC) __irda_task_delete);
+	spin_lock(&dongles->hb_spinlock);
 	hashbin_delete(dongles, NULL);
+	spin_unlock(&dongles->hb_spinlock);
 }
 
 /*
@@ -424,25 +426,34 @@ int irda_device_txqueue_empty(struct net
 dongle_t *irda_device_dongle_init(struct net_device *dev, int type)
 {
 	struct dongle_reg *reg;
-	dongle_t *dongle;
+	dongle_t *dongle = NULL;
 
-	ASSERT(dev != NULL, return NULL;);
+	might_sleep();
+
+	spin_lock(&dongles->hb_spinlock);
+	reg = hashbin_find(dongles, type, NULL);
 
 #ifdef CONFIG_KMOD
-	ASSERT(!in_interrupt(), return NULL;);
 	/* Try to load the module needed */
-	request_module("irda-dongle-%d", type);
+	if (!reg && capable(CAP_SYS_MODULE)) {
+		spin_unlock(&dongles->hb_spinlock);
+	
+		request_module("irda-dongle-%d", type);
+		
+		spin_lock(&dongles->hb_spinlock);
+		reg = hashbin_find(dongles, type, NULL);
+	}
 #endif
 
-	if (!(reg = hashbin_lock_find(dongles, type, NULL))) {
-		ERROR("IrDA: Unable to find requested dongle\n");
-		return NULL;
+	if (!reg || !try_module_get(reg->owner) ) {
+		ERROR("IrDA: Unable to find requested dongle type %x\n", type);
+		goto out;
 	}
 
 	/* Allocate dongle info for this instance */
 	dongle = kmalloc(sizeof(dongle_t), GFP_KERNEL);
 	if (!dongle)
-		return NULL;
+		goto out;
 
 	memset(dongle, 0, sizeof(dongle_t));
 
@@ -450,6 +461,8 @@ dongle_t *irda_device_dongle_init(struct
 	dongle->issue = reg;
 	dongle->dev = dev;
 
+ out:
+	spin_unlock(&dongles->hb_spinlock);
 	return dongle;
 }
 
@@ -461,7 +474,7 @@ int irda_device_dongle_cleanup(dongle_t 
 	ASSERT(dongle != NULL, return -1;);
 
 	dongle->issue->close(dongle);
-
+	module_put(dongle->issue->owner);
 	kfree(dongle);
 
 	return 0;
@@ -472,14 +485,16 @@ int irda_device_dongle_cleanup(dongle_t 
  */
 int irda_device_register_dongle(struct dongle_reg *new)
 {
+	spin_lock(&dongles->hb_spinlock);
 	/* Check if this dongle has been registered before */
-	if (hashbin_lock_find(dongles, new->type, NULL)) {
-		MESSAGE("%s: Dongle already registered\n", __FUNCTION__);
-                return 0;
-        }
-
-	/* Insert IrDA dongle into hashbin */
-	hashbin_insert(dongles, (irda_queue_t *) new, new->type, NULL);
+	if (hashbin_find(dongles, new->type, NULL)) {
+		MESSAGE("%s: Dongle type %x already registered\n", 
+			__FUNCTION__, new->type);
+        } else {
+		/* Insert IrDA dongle into hashbin */
+		hashbin_insert(dongles, (irda_queue_t *) new, new->type, NULL);
+	}
+	spin_unlock(&dongles->hb_spinlock);
 
         return 0;
 }
@@ -494,11 +509,11 @@ void irda_device_unregister_dongle(struc
 {
 	struct dongle *node;
 
+	spin_lock(&dongles->hb_spinlock);
 	node = hashbin_remove(dongles, dongle->type, NULL);
-	if (!node) {
+	if (!node) 
 		ERROR("%s: dongle not found!\n", __FUNCTION__);
-		return;
-	}
+	spin_unlock(&dongles->hb_spinlock);
 }
 
 /*

  reply	other threads:[~2003-10-03 17:21 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2003-10-02 22:20 [PATCH] (1/11) Irda dongle module owner support Stephen Hemminger
2003-10-02 23:33 ` Jean Tourrilhes
2003-10-03 17:21   ` Stephen Hemminger [this message]
2003-10-03 17:31     ` [PATCH] (1/11) Irda dongle module owner support (revised) Jean Tourrilhes
2003-10-04  6:06     ` David S. Miller
2003-10-03 13:55 ` [PATCH] (1/11) Irda dongle module owner support David S. Miller
2003-10-06 23:23 ` Jean Tourrilhes

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=20031003102133.2e5a41a2.shemminger@osdl.org \
    --to=shemminger@osdl.org \
    --cc=davem@redhat.com \
    --cc=irda-users@lists.sourceforge.net \
    --cc=jt@bougret.hpl.hp.com \
    --cc=jt@hpl.hp.com \
    --cc=netdev@oss.sgi.com \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).