From: Stephen Hemminger <shemminger@osdl.org>
To: "David S. Miller" <davem@redhat.com>
Cc: netdev@oss.sgi.com
Subject: [PATCH] convert slip driver to alloc_netdev
Date: Fri, 13 Jun 2003 16:09:42 -0700 [thread overview]
Message-ID: <20030613160942.384ca2c3.shemminger@osdl.org> (raw)
Slightly more complicated than earlier patches. Convert slip from having an array of control block
pointers that containing net_device's to an array of net_device pointers. The slip private data is
allocated with alloc_netdev.
Also changed the exit loop to use a schedule_timeout instead of yield. That should work
better on 2.5 and we can sleep there.
This patch is against 2.5.70 with all the earlier net patches applied.
Tested with dedicated serial cable between 2.4 and SUT.
diff -Nru a/drivers/net/slip.c b/drivers/net/slip.c
--- a/drivers/net/slip.c Fri Jun 13 16:03:27 2003
+++ b/drivers/net/slip.c Fri Jun 13 16:03:27 2003
@@ -83,12 +83,7 @@
#define SLIP_VERSION "0.8.4-NET3.019-NEWTTY"
-
-typedef struct slip_ctrl {
- struct slip ctrl; /* SLIP things */
- struct net_device dev; /* the device */
-} slip_ctrl_t;
-static slip_ctrl_t **slip_ctrls;
+static struct net_device **slip_devs;
int slip_maxdev = SL_NRUNIT; /* Can be overridden with insmod! */
MODULE_PARM(slip_maxdev, "i");
@@ -624,32 +619,45 @@
*/
dev->mtu = sl->mtu;
- dev->hard_start_xmit = sl_xmit;
+ dev->type = ARPHRD_SLIP + sl->mode;
#ifdef SL_CHECK_TRANSMIT
dev->tx_timeout = sl_tx_timeout;
dev->watchdog_timeo = 20*HZ;
#endif
+ return 0;
+}
+
+
+static void sl_uninit(struct net_device *dev)
+{
+ struct slip *sl = (struct slip*)(dev->priv);
+
+ sl_free_bufs(sl);
+}
+
+static void sl_setup(struct net_device *dev)
+{
+ dev->init = sl_init;
+ dev->uninit = sl_uninit;
dev->open = sl_open;
+ dev->destructor = (void (*)(struct net_device *))kfree;
dev->stop = sl_close;
dev->get_stats = sl_get_stats;
dev->change_mtu = sl_change_mtu;
+ dev->hard_start_xmit = sl_xmit;
#ifdef CONFIG_SLIP_SMART
dev->do_ioctl = sl_ioctl;
#endif
dev->hard_header_len = 0;
dev->addr_len = 0;
- dev->type = ARPHRD_SLIP + sl->mode;
dev->tx_queue_len = 10;
SET_MODULE_OWNER(dev);
/* New-style flags. */
dev->flags = IFF_NOARP|IFF_POINTOPOINT|IFF_MULTICAST;
-
- return 0;
}
-
/******************************************
Routines looking at TTY side.
******************************************/
@@ -702,52 +710,57 @@
static void sl_sync(void)
{
int i;
+ struct net_device *dev;
+ struct slip *sl;
for (i = 0; i < slip_maxdev; i++) {
- slip_ctrl_t *slp = slip_ctrls[i];
- if (slp == NULL)
+ if ((dev = slip_devs[i]) == NULL)
break;
- if (slp->ctrl.tty || slp->ctrl.leased)
+
+ sl = dev->priv;
+ if (sl->tty || sl->leased)
continue;
- if (slp->dev.flags&IFF_UP)
- dev_close(&slp->dev);
+ if (dev->flags&IFF_UP)
+ dev_close(dev);
}
}
+
/* Find a free SLIP channel, and link in this `tty' line. */
static struct slip *
sl_alloc(dev_t line)
{
- struct slip *sl;
- slip_ctrl_t *slp = NULL;
int i;
int sel = -1;
int score = -1;
+ struct net_device *dev = NULL;
+ struct slip *sl;
- if (slip_ctrls == NULL)
+ if (slip_devs == NULL)
return NULL; /* Master array missing ! */
for (i = 0; i < slip_maxdev; i++) {
- slp = slip_ctrls[i];
- if (slp == NULL)
+ dev = slip_devs[i];
+ if (dev == NULL)
break;
- if (slp->ctrl.leased) {
- if (slp->ctrl.line != line)
+ sl = dev->priv;
+ if (sl->leased) {
+ if (sl->line != line)
continue;
- if (slp->ctrl.tty)
+ if (sl->tty)
return NULL;
/* Clear ESCAPE & ERROR flags */
- slp->ctrl.flags &= (1 << SLF_INUSE);
- return &slp->ctrl;
+ sl->flags &= (1 << SLF_INUSE);
+ return sl;
}
- if (slp->ctrl.tty)
+ if (sl->tty)
continue;
- if (current->pid == slp->ctrl.pid) {
- if (slp->ctrl.line == line && score < 3) {
+ if (current->pid == sl->pid) {
+ if (sl->line == line && score < 3) {
sel = i;
score = 3;
continue;
@@ -758,7 +771,7 @@
}
continue;
}
- if (slp->ctrl.line == line && score < 1) {
+ if (sl->line == line && score < 1) {
sel = i;
score = 1;
continue;
@@ -771,10 +784,11 @@
if (sel >= 0) {
i = sel;
- slp = slip_ctrls[i];
+ dev = slip_devs[i];
if (score > 1) {
- slp->ctrl.flags &= (1 << SLF_INUSE);
- return &slp->ctrl;
+ sl = dev->priv;
+ sl->flags &= (1 << SLF_INUSE);
+ return sl;
}
}
@@ -782,26 +796,32 @@
if (i >= slip_maxdev)
return NULL;
- if (slp) {
- if (test_bit(SLF_INUSE, &slp->ctrl.flags)) {
- unregister_netdevice(&slp->dev);
- sl_free_bufs(&slp->ctrl);
+ if (dev) {
+ sl = dev->priv;
+ if (test_bit(SLF_INUSE, &sl->flags)) {
+ unregister_netdevice(dev);
+ dev = NULL;
+ slip_devs[i] = NULL;
}
- } else if ((slp = (slip_ctrl_t *)kmalloc(sizeof(slip_ctrl_t),GFP_KERNEL)) == NULL)
- return NULL;
+ }
+
+ if (!dev) {
+ char name[IFNAMSIZ];
+ sprintf(name, "sl%d", i);
- memset(slp, 0, sizeof(slip_ctrl_t));
+ dev = alloc_netdev(sizeof(*sl), name, sl_setup);
+ if (!dev)
+ return NULL;
+ dev->base_addr = i;
+ }
+
+ sl = dev->priv;
- sl = &slp->ctrl;
/* Initialize channel control data */
sl->magic = SLIP_MAGIC;
- sl->dev = &slp->dev;
+ sl->dev = dev;
spin_lock_init(&sl->lock);
sl->mode = SL_MODE_DEFAULT;
- sprintf(slp->dev.name, "sl%d", i);
- slp->dev.base_addr = i;
- slp->dev.priv = (void*)sl;
- slp->dev.init = sl_init;
#ifdef CONFIG_SLIP_SMART
init_timer(&sl->keepalive_timer); /* initialize timer_list struct */
sl->keepalive_timer.data=(unsigned long)sl;
@@ -810,8 +830,9 @@
sl->outfill_timer.data=(unsigned long)sl;
sl->outfill_timer.function=sl_outfill;
#endif
- slip_ctrls[i] = slp;
- return &slp->ctrl;
+ slip_devs[i] = dev;
+
+ return sl;
}
/*
@@ -865,12 +886,10 @@
if ((err = sl_alloc_bufs(sl, SL_MTU)) != 0)
goto err_free_chan;
- if (register_netdevice(sl->dev)) {
- sl_free_bufs(sl);
- goto err_free_chan;
- }
-
set_bit(SLF_INUSE, &sl->flags);
+
+ if ((err = register_netdevice(sl->dev)))
+ goto err_free_bufs;
}
#ifdef CONFIG_SLIP_SMART
@@ -888,6 +907,9 @@
rtnl_unlock();
return sl->dev->base_addr;
+err_free_bufs:
+ sl_free_bufs(sl);
+
err_free_chan:
sl->tty = NULL;
tty->disc_data = NULL;
@@ -1335,14 +1357,14 @@
printk(KERN_INFO "SLIP linefill/keepalive option.\n");
#endif
- slip_ctrls = kmalloc(sizeof(void*)*slip_maxdev, GFP_KERNEL);
- if (!slip_ctrls) {
- printk(KERN_ERR "SLIP: Can't allocate slip_ctrls[] array! Uaargh! (-> No SLIP available)\n");
+ slip_devs = kmalloc(sizeof(struct net_device *)*slip_maxdev, GFP_KERNEL);
+ if (!slip_devs) {
+ printk(KERN_ERR "SLIP: Can't allocate slip devices array! Uaargh! (-> No SLIP available)\n");
return -ENOMEM;
}
/* Clear the pointer array, we allocate devices when we need them */
- memset(slip_ctrls, 0, sizeof(void*)*slip_maxdev); /* Pointers */
+ memset(slip_devs, 0, sizeof(struct net_device *)*slip_maxdev);
/* Fill in our line protocol discipline, and register it */
if ((status = tty_register_ldisc(N_SLIP, &sl_ldisc)) != 0) {
@@ -1354,51 +1376,59 @@
static void __exit slip_exit(void)
{
int i;
+ struct net_device *dev;
+ struct slip *sl;
+ unsigned long timeout = jiffies + HZ;
+ int busy = 0;
- if (slip_ctrls != NULL) {
- unsigned long timeout = jiffies + HZ;
- int busy = 0;
+ if (slip_devs == NULL)
+ return;
- /* First of all: check for active disciplines and hangup them.
- */
- do {
- if (busy)
- yield();
-
- busy = 0;
- local_bh_disable();
- for (i = 0; i < slip_maxdev; i++) {
- struct slip_ctrl *slc = slip_ctrls[i];
- if (!slc)
- continue;
- spin_lock(&slc->ctrl.lock);
- if (slc->ctrl.tty) {
- busy++;
- tty_hangup(slc->ctrl.tty);
- }
- spin_unlock(&slc->ctrl.lock);
- }
- local_bh_enable();
- } while (busy && time_before(jiffies, timeout));
+ /* First of all: check for active disciplines and hangup them.
+ */
+ do {
+ if (busy) {
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(HZ / 10);
+ current->state = TASK_RUNNING;
+ }
+ busy = 0;
for (i = 0; i < slip_maxdev; i++) {
- struct slip_ctrl *slc = slip_ctrls[i];
- if (slc) {
- unregister_netdev(&slc->dev);
- if (slc->ctrl.tty) {
- printk(KERN_ERR "%s: tty discipline is still running\n", slc->dev.name);
- /* Intentionally leak the control block. */
- } else {
- sl_free_bufs(&slc->ctrl);
- kfree(slc);
- }
- slip_ctrls[i] = NULL;
+ dev = slip_devs[i];
+ if (!dev)
+ continue;
+ sl = dev->priv;
+ spin_lock_bh(&sl->lock);
+ if (sl->tty) {
+ busy++;
+ tty_hangup(sl->tty);
}
+ spin_unlock_bh(&sl->lock);
}
+ } while (busy && time_before(jiffies, timeout));
+
+
+ for (i = 0; i < slip_maxdev; i++) {
+ dev = slip_devs[i];
+ if (!dev)
+ continue;
+ slip_devs[i] = NULL;
+
+ sl = dev->priv;
+ if (sl->tty) {
+ printk(KERN_ERR "%s: tty discipline still running\n",
+ dev->name);
+ /* Intentionally leak the control block. */
+ dev->destructor = NULL;
+ }
- kfree(slip_ctrls);
- slip_ctrls = NULL;
+ unregister_netdev(dev);
}
+
+ kfree(slip_devs);
+ slip_devs = NULL;
+
if ((i = tty_register_ldisc(N_SLIP, NULL)))
{
printk(KERN_ERR "SLIP: can't unregister line discipline (err = %d)\n", i);
next reply other threads:[~2003-06-13 23:09 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2003-06-13 23:09 Stephen Hemminger [this message]
2003-06-15 7:42 ` [PATCH] convert slip driver to alloc_netdev David S. Miller
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=20030613160942.384ca2c3.shemminger@osdl.org \
--to=shemminger@osdl.org \
--cc=davem@redhat.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).