Commit 1f4fa314 authored by Kai Germaschewski's avatar Kai Germaschewski

ISDN/PPP: Reference struct ipppd directly

Instead of just recording the slot number and then retrieving
the ipppd via that, we can now just keep a pointer and get a
reference which makes sure that it does not go away until
we drop the reference.
parent 3ff0f2d6
...@@ -369,7 +369,7 @@ isdn_net_addif(char *name, isdn_net_local *mlp) ...@@ -369,7 +369,7 @@ isdn_net_addif(char *name, isdn_net_local *mlp)
idev->pre_channel = -1; idev->pre_channel = -1;
idev->exclusive = -1; idev->exclusive = -1;
idev->ppp_slot = -1; idev->ipppd = NULL;
idev->pppbind = -1; idev->pppbind = -1;
init_timer(&idev->dial_timer); init_timer(&idev->dial_timer);
......
...@@ -32,15 +32,23 @@ struct ipppd { ...@@ -32,15 +32,23 @@ struct ipppd {
atomic_t refcnt; atomic_t refcnt;
}; };
/* We use reference counting for struct ipppd. It is alloced on
* open() on /dev/ipppX and saved into file->private, making for one
* reference. release() will release this reference, after all other
* references are gone, the destructor frees it.
*
* Another reference is taken by isdn_ppp_bind() and freed by
* isdn_ppp_unbind(). The callbacks from isdn_net_lib.c happen only
* between isdn_ppp_bind() and isdn_ppp_unbind(), i.e. access to
* idev->ipppd is safe without further locking.
*/
/* Prototypes */ /* Prototypes */
static void isdn_ppp_push_higher(isdn_net_local *lp, isdn_net_dev *idev, static void isdn_ppp_push_higher(isdn_net_local *lp, isdn_net_dev *idev,
struct sk_buff *skb, int proto); struct sk_buff *skb, int proto);
static int isdn_ppp_if_get_unit(char *namebuf); static int isdn_ppp_if_get_unit(char *namebuf);
static int isdn_ppp_set_compressor(struct ipppd *is,struct isdn_ppp_comp_data *); static int isdn_ppp_set_compressor(struct ipppd *is,struct isdn_ppp_comp_data *);
static void
ipppd_closewait(struct ipppd *ipppd);
static void static void
isdn_ppp_receive_ccp(isdn_net_dev * net_dev, isdn_net_local * lp, isdn_ppp_receive_ccp(isdn_net_dev * net_dev, isdn_net_local * lp,
struct sk_buff *skb,int proto); struct sk_buff *skb,int proto);
...@@ -183,16 +191,12 @@ isdn_ppp_push_header(isdn_net_dev *idev, struct sk_buff *skb, u16 proto) ...@@ -183,16 +191,12 @@ isdn_ppp_push_header(isdn_net_dev *idev, struct sk_buff *skb, u16 proto)
* in this case we bind another lp to the master device * in this case we bind another lp to the master device
*/ */
static void static void
isdn_ppp_free(isdn_net_dev *idev) isdn_ppp_unbind(isdn_net_dev *idev)
{ {
unsigned long flags;
struct ipppd *is; struct ipppd *is;
// FIXME much of this wants to rather happen when disconnected() // FIXME much of this wants to rather happen when disconnected()
save_flags(flags);
cli();
#ifdef CONFIG_ISDN_MPP #ifdef CONFIG_ISDN_MPP
spin_lock(&idev->pb->lock); spin_lock(&idev->pb->lock);
if (lp->netdev->pb->ref_ct == 1) /* last link in queue? */ if (lp->netdev->pb->ref_ct == 1) /* last link in queue? */
...@@ -201,32 +205,29 @@ isdn_ppp_free(isdn_net_dev *idev) ...@@ -201,32 +205,29 @@ isdn_ppp_free(isdn_net_dev *idev)
lp->netdev->pb->ref_ct--; lp->netdev->pb->ref_ct--;
spin_unlock(&lp->netdev->pb->lock); spin_unlock(&lp->netdev->pb->lock);
#endif /* CONFIG_ISDN_MPP */ #endif /* CONFIG_ISDN_MPP */
if (idev->ppp_slot < 0 || idev->ppp_slot > ISDN_MAX_CHANNELS) { is = idev->ipppd;
printk(KERN_ERR "%s: ppp_slot(%d) now invalid\n", if (!is) {
__FUNCTION__ , idev->ppp_slot); isdn_BUG();
restore_flags(flags);
return; return;
} }
is = ipppd_get(idev->ppp_slot); if (is->state & IPPP_CONNECT) {
if (!is) is->state = IPPP_CLOSEWAIT;
return; wake_up(&is->wq);
} else if (is->state & IPPP_ASSIGNED) {
if (is->state & IPPP_CONNECT)
ipppd_closewait(is); /* force wakeup on ippp device */
else if (is->state & IPPP_ASSIGNED)
is->state = IPPP_OPEN; /* fallback to 'OPEN but not ASSIGNED' state */ is->state = IPPP_OPEN; /* fallback to 'OPEN but not ASSIGNED' state */
} else {
isdn_BUG();
}
if (is->debug & 0x1) if (is->debug & 0x1)
printk(KERN_DEBUG "isdn_ppp_free %d %p\n", idev->ppp_slot, is->idev); printk(KERN_DEBUG "isdn_ppp_unbind %p %p\n", idev, is);
is->idev = NULL; /* link is down .. set lp to NULL */ is->idev = NULL;
idev->ppp_slot = -1; /* is this OK ?? */ /* lose the reference we took on isdn_ppp_bind */
ipppd_put(is); ipppd_put(is);
idev->ipppd = NULL;
ippp_ccp_free(idev->ccp); ippp_ccp_free(idev->ccp);
restore_flags(flags);
return; return;
} }
...@@ -241,15 +242,20 @@ isdn_ppp_bind(isdn_net_dev *idev) ...@@ -241,15 +242,20 @@ isdn_ppp_bind(isdn_net_dev *idev)
unsigned long flags; unsigned long flags;
int retval = 0; int retval = 0;
if (idev->ipppd) {
isdn_BUG();
return 0;
}
spin_lock_irqsave(&ipppds_lock, flags); spin_lock_irqsave(&ipppds_lock, flags);
if (idev->pppbind < 0) { /* device bound to ippp device ? */ if (idev->pppbind < 0) { /* device bound to ippp device ? */
struct list_head *l; struct list_head *l;
char exclusive[ISDN_MAX_CHANNELS]; /* exclusive flags */ char exclusive[NR_IPPPDS]; /* exclusive flags */
memset(exclusive, 0, ISDN_MAX_CHANNELS); memset(exclusive, 0, NR_IPPPDS);
/* step through net devices to find exclusive minors */ /* step through net devices to find exclusive minors */
list_for_each(l, &isdn_net_devs) { list_for_each(l, &isdn_net_devs) {
isdn_net_dev *p = list_entry(l, isdn_net_dev, global_list); isdn_net_dev *p = list_entry(l, isdn_net_dev, global_list);
if (p->pppbind >= 0) if (p->pppbind >= 0 && p->pppbind < NR_IPPPDS)
exclusive[p->pppbind] = 1; exclusive[p->pppbind] = 1;
} }
/* /*
...@@ -287,14 +293,13 @@ isdn_ppp_bind(isdn_net_dev *idev) ...@@ -287,14 +293,13 @@ isdn_ppp_bind(isdn_net_dev *idev)
goto err; goto err;
} }
ipppds[i]->state = IPPP_OPEN | IPPP_ASSIGNED; /* assigned to a netdevice but not connected */
spin_unlock_irqrestore(&ipppds_lock, flags);
ipppds[i]->idev = idev;
ipppds[i]->unit = unit; ipppds[i]->unit = unit;
ipppds[i]->state = IPPP_OPEN | IPPP_ASSIGNED;
ipppds[i]->idev = idev;
/* we hold a reference until isdn_ppp_unbind() */
idev->ipppd = __ipppd_get(ipppds[i]);
spin_unlock_irqrestore(&ipppds_lock, flags);
idev->ppp_slot = i;
idev->pppcfg = 0; /* config flags */ idev->pppcfg = 0; /* config flags */
/* seq no last seen, maybe set to bundle min, when joining? */ /* seq no last seen, maybe set to bundle min, when joining? */
idev->pppseq = -1; idev->pppseq = -1;
...@@ -315,8 +320,11 @@ isdn_ppp_bind(isdn_net_dev *idev) ...@@ -315,8 +320,11 @@ isdn_ppp_bind(isdn_net_dev *idev)
retval = isdn_ppp_mp_init(lp, NULL); retval = isdn_ppp_mp_init(lp, NULL);
#endif /* CONFIG_ISDN_MPP */ #endif /* CONFIG_ISDN_MPP */
out: out:
if (retval) if (retval) {
ipppds[i]->state = IPPP_OPEN; idev->ipppd->state = IPPP_OPEN;
ipppd_put(idev->ipppd);
idev->ipppd = NULL;
}
return retval; return retval;
...@@ -331,28 +339,12 @@ isdn_ppp_bind(isdn_net_dev *idev) ...@@ -331,28 +339,12 @@ isdn_ppp_bind(isdn_net_dev *idev)
*/ */
static void static void
isdn_ppp_wakeup_daemon(isdn_net_dev *idev) isdn_ppp_connected(isdn_net_dev *idev)
{ {
struct ipppd *ipppd = ipppd_get(idev->ppp_slot); struct ipppd *ipppd = idev->ipppd;
if (!ipppd)
return;
ipppd->state = IPPP_OPEN | IPPP_CONNECT | IPPP_NOBLOCK; ipppd->state = IPPP_OPEN | IPPP_CONNECT | IPPP_NOBLOCK;
wake_up(&ipppd->wq); wake_up(&ipppd->wq);
ipppd_put(ipppd);
}
/*
* there was a hangup on the netdevice
* force wakeup of the ippp device
* go into 'device waits for release' state
*/
static void
ipppd_closewait(struct ipppd *ipppd)
{
wake_up(&ipppd->wq);
ipppd->state = IPPP_CLOSEWAIT;
} }
/* /*
...@@ -837,7 +829,7 @@ ipppd_write(struct file *file, const char *buf, size_t count, loff_t *off) ...@@ -837,7 +829,7 @@ ipppd_write(struct file *file, const char *buf, size_t count, loff_t *off)
} }
if (is->debug & 0x40) { if (is->debug & 0x40) {
printk(KERN_DEBUG "ppp xmit: len %d\n", (int) skb->len); printk(KERN_DEBUG "ppp xmit: len %d\n", (int) skb->len);
isdn_ppp_frame_log("xmit", skb->data, skb->len, 32,is->unit,idev->ppp_slot); isdn_ppp_frame_log("xmit", skb->data, skb->len, 32,is->unit,-1);
} }
isdn_ppp_send_ccp(idev,idev->mlp,skb); /* keeps CCP/compression states in sync */ isdn_ppp_send_ccp(idev,idev->mlp,skb); /* keeps CCP/compression states in sync */
...@@ -976,22 +968,22 @@ static void isdn_ppp_receive(isdn_net_local *lp, isdn_net_dev *idev, ...@@ -976,22 +968,22 @@ static void isdn_ppp_receive(isdn_net_local *lp, isdn_net_dev *idev,
struct ipppd *is; struct ipppd *is;
int proto; int proto;
is = ipppd_get(idev->ppp_slot); is = idev->ipppd;
if (!is) if (!is)
goto err; goto err;
if (is->debug & 0x4) { if (is->debug & 0x4) {
printk(KERN_DEBUG "ippp_receive: is:%p lp:%p slot:%d unit:%d len:%d\n", printk(KERN_DEBUG "ippp_receive: is:%p lp:%p unit:%d len:%d\n",
is,lp,idev->ppp_slot,is->unit,(int) skb->len); is, lp, is->unit, skb->len);
isdn_ppp_frame_log("receive", skb->data, skb->len, 32,is->unit,idev->ppp_slot); isdn_ppp_frame_log("receive", skb->data, skb->len, 32,is->unit,-1);
} }
if (isdn_ppp_skip_ac(idev, skb) < 0) if (isdn_ppp_skip_ac(idev, skb) < 0)
goto err_put; goto err;
proto = isdn_ppp_strip_proto(skb); proto = isdn_ppp_strip_proto(skb);
if (proto < 0) if (proto < 0)
goto err_put; goto err;
/* Don't reset huptimer on LCP packets. */ /* Don't reset huptimer on LCP packets. */
if (proto != PPP_LCP) if (proto != PPP_LCP)
...@@ -1015,11 +1007,8 @@ static void isdn_ppp_receive(isdn_net_local *lp, isdn_net_dev *idev, ...@@ -1015,11 +1007,8 @@ static void isdn_ppp_receive(isdn_net_local *lp, isdn_net_dev *idev,
#else #else
isdn_ppp_push_higher(lp, idev, skb, proto); isdn_ppp_push_higher(lp, idev, skb, proto);
#endif #endif
ipppd_put(is);
return; return;
err_put:
ipppd_put(is);
err: err:
kfree_skb(skb); kfree_skb(skb);
} }
...@@ -1034,19 +1023,15 @@ isdn_ppp_push_higher(isdn_net_local *lp, isdn_net_dev *idev, ...@@ -1034,19 +1023,15 @@ isdn_ppp_push_higher(isdn_net_local *lp, isdn_net_dev *idev,
struct sk_buff *skb, int proto) struct sk_buff *skb, int proto)
{ {
struct net_device *dev = &lp->dev; struct net_device *dev = &lp->dev;
struct ipppd *is; struct ipppd *is = idev->ipppd;
is = ipppd_get(idev->ppp_slot);
if (!is)
goto drop;
if (is->debug & 0x10) { if (is->debug & 0x10) {
printk(KERN_DEBUG "push, skb %d %04x\n", (int) skb->len, proto); printk(KERN_DEBUG "push, skb %d %04x\n", (int) skb->len, proto);
isdn_ppp_frame_log("rpush", skb->data, skb->len, 32,is->unit, idev->ppp_slot); isdn_ppp_frame_log("rpush", skb->data, skb->len, 32,is->unit, -1);
} }
skb = ippp_ccp_decompress(lp->ccp, skb, &proto); skb = ippp_ccp_decompress(lp->ccp, skb, &proto);
if (!skb) // decompression error if (!skb) // decompression error
goto put; goto out;
switch (proto) { switch (proto) {
case PPP_IPX: /* untested */ case PPP_IPX: /* untested */
...@@ -1062,14 +1047,14 @@ isdn_ppp_push_higher(isdn_net_local *lp, isdn_net_dev *idev, ...@@ -1062,14 +1047,14 @@ isdn_ppp_push_higher(isdn_net_local *lp, isdn_net_dev *idev,
case PPP_COMP: case PPP_COMP:
case PPP_COMPFRAG: case PPP_COMPFRAG:
printk(KERN_INFO "isdn_ppp: unexpected compressed frame dropped\n"); printk(KERN_INFO "isdn_ppp: unexpected compressed frame dropped\n");
goto drop_put; goto drop;
#ifdef CONFIG_ISDN_PPP_VJ #ifdef CONFIG_ISDN_PPP_VJ
case PPP_VJC_UNCOMP: case PPP_VJC_UNCOMP:
if (is->debug & 0x20) if (is->debug & 0x20)
printk(KERN_DEBUG "isdn_ppp: VJC_UNCOMP\n"); printk(KERN_DEBUG "isdn_ppp: VJC_UNCOMP\n");
if (slhc_remember(lp->slcomp, skb->data, skb->len) <= 0) { if (slhc_remember(lp->slcomp, skb->data, skb->len) <= 0) {
printk(KERN_WARNING "isdn_ppp: received illegal VJC_UNCOMP frame!\n"); printk(KERN_WARNING "isdn_ppp: received illegal VJC_UNCOMP frame!\n");
goto drop_put; goto drop;
} }
skb->protocol = htons(ETH_P_IP); skb->protocol = htons(ETH_P_IP);
break; break;
...@@ -1084,7 +1069,7 @@ isdn_ppp_push_higher(isdn_net_local *lp, isdn_net_dev *idev, ...@@ -1084,7 +1069,7 @@ isdn_ppp_push_higher(isdn_net_local *lp, isdn_net_dev *idev,
if (!skb) { if (!skb) {
printk(KERN_WARNING "%s: Memory squeeze, dropping packet.\n", dev->name); printk(KERN_WARNING "%s: Memory squeeze, dropping packet.\n", dev->name);
skb = skb_old; skb = skb_old;
goto drop_put; goto drop;
} }
skb_put(skb, skb_old->len + 128); skb_put(skb, skb_old->len + 128);
memcpy(skb->data, skb_old->data, skb_old->len); memcpy(skb->data, skb_old->data, skb_old->len);
...@@ -1092,7 +1077,7 @@ isdn_ppp_push_higher(isdn_net_local *lp, isdn_net_dev *idev, ...@@ -1092,7 +1077,7 @@ isdn_ppp_push_higher(isdn_net_local *lp, isdn_net_dev *idev,
skb->data, skb_old->len); skb->data, skb_old->len);
kfree_skb(skb_old); kfree_skb(skb_old);
if (pkt_len < 0) if (pkt_len < 0)
goto drop_put; goto drop;
skb_trim(skb, pkt_len); skb_trim(skb, pkt_len);
skb->protocol = htons(ETH_P_IP); skb->protocol = htons(ETH_P_IP);
...@@ -1107,14 +1092,14 @@ isdn_ppp_push_higher(isdn_net_local *lp, isdn_net_dev *idev, ...@@ -1107,14 +1092,14 @@ isdn_ppp_push_higher(isdn_net_local *lp, isdn_net_dev *idev,
if(skb->data[0] == CCP_RESETREQ || if(skb->data[0] == CCP_RESETREQ ||
skb->data[0] == CCP_RESETACK) { skb->data[0] == CCP_RESETACK) {
kfree_skb(skb); kfree_skb(skb);
goto put; goto out;
} }
/* fall through */ /* fall through */
default: default:
// FIXME use skb directly // FIXME use skb directly
ipppd_queue_read(is, proto, skb->data, skb->len); ipppd_queue_read(is, proto, skb->data, skb->len);
kfree_skb(skb); kfree_skb(skb);
goto put; goto out;
} }
/* Reset hangup-timer */ /* Reset hangup-timer */
...@@ -1123,12 +1108,9 @@ isdn_ppp_push_higher(isdn_net_local *lp, isdn_net_dev *idev, ...@@ -1123,12 +1108,9 @@ isdn_ppp_push_higher(isdn_net_local *lp, isdn_net_dev *idev,
skb->dev = dev; skb->dev = dev;
netif_rx(skb); netif_rx(skb);
/* net_dev->local->stats.rx_packets++; done in isdn_net.c */ /* net_dev->local->stats.rx_packets++; done in isdn_net.c */
put: out:
ipppd_put(is);
return; return;
drop_put:
ipppd_put(is);
drop: drop:
lp->stats.rx_dropped++; lp->stats.rx_dropped++;
kfree_skb(skb); kfree_skb(skb);
...@@ -1148,24 +1130,13 @@ isdn_ppp_start_xmit(struct sk_buff *skb, struct net_device *ndev) ...@@ -1148,24 +1130,13 @@ isdn_ppp_start_xmit(struct sk_buff *skb, struct net_device *ndev)
isdn_net_local *mlp = ndev->priv; isdn_net_local *mlp = ndev->priv;
isdn_net_dev *idev = list_entry(mlp->online.next, isdn_net_dev, online); isdn_net_dev *idev = list_entry(mlp->online.next, isdn_net_dev, online);
unsigned int proto = PPP_IP; /* 0x21 */ unsigned int proto = PPP_IP; /* 0x21 */
struct ipppd *ipt,*ipts; struct ipppd *ipppd;
ndev->trans_start = jiffies; ndev->trans_start = jiffies;
if (list_empty(&mlp->online)) if (list_empty(&mlp->online))
return isdn_net_autodial(skb, ndev); return isdn_net_autodial(skb, ndev);
ipts = ipppd_get(idev->ppp_slot);
if (!ipts) {
isdn_BUG();
goto err;
}
if (!(idev->pppcfg & SC_ENABLE_IP)) { /* PPP connected ? */
printk(KERN_INFO "%s: IP frame delayed.\n", ndev->name);
goto err_put;
}
switch (ntohs(skb->protocol)) { switch (ntohs(skb->protocol)) {
case ETH_P_IP: case ETH_P_IP:
proto = PPP_IP; proto = PPP_IP;
...@@ -1177,29 +1148,29 @@ isdn_ppp_start_xmit(struct sk_buff *skb, struct net_device *ndev) ...@@ -1177,29 +1148,29 @@ isdn_ppp_start_xmit(struct sk_buff *skb, struct net_device *ndev)
printk(KERN_ERR "isdn_ppp: skipped unsupported protocol: %#x.\n", printk(KERN_ERR "isdn_ppp: skipped unsupported protocol: %#x.\n",
skb->protocol); skb->protocol);
dev_kfree_skb(skb); dev_kfree_skb(skb);
goto put; goto out;
} }
idev = isdn_net_get_xmit_dev(mlp); idev = isdn_net_get_xmit_dev(mlp);
if (!idev) { if (!idev) {
printk(KERN_INFO "%s: IP frame delayed.\n", ndev->name);
goto stop;
}
if (!(idev->pppcfg & SC_ENABLE_IP)) { /* PPP connected ? */
isdn_BUG(); isdn_BUG();
goto err_put; goto stop;
} }
ipppd = idev->ipppd;
ipt = ipppd_get(idev->ppp_slot);
if (!ipt)
goto put;
idev->huptimer = 0; idev->huptimer = 0;
/* /*
* after this line .. requeueing in the device queue is no longer allowed!!! * after this line .. requeueing in the device queue is no longer allowed!!!
*/ */
if (ipt->debug & 0x4) if (ipppd->debug & 0x4)
printk(KERN_DEBUG "xmit skb, len %d\n", (int) skb->len); printk(KERN_DEBUG "xmit skb, len %d\n", (int) skb->len);
if (ipts->debug & 0x40) if (ipppd->debug & 0x40)
isdn_ppp_frame_log("xmit0", skb->data, skb->len, 32,ipts->unit,idev->ppp_slot); isdn_ppp_frame_log("xmit0", skb->data, skb->len, 32, ipppd->unit, -1);
#ifdef CONFIG_ISDN_PPP_VJ #ifdef CONFIG_ISDN_PPP_VJ
if (proto == PPP_IP && idev->pppcfg & SC_COMP_TCP) { /* ipts here? probably yes, but check this again */ if (proto == PPP_IP && idev->pppcfg & SC_COMP_TCP) { /* ipts here? probably yes, but check this again */
...@@ -1257,7 +1228,7 @@ isdn_ppp_start_xmit(struct sk_buff *skb, struct net_device *ndev) ...@@ -1257,7 +1228,7 @@ isdn_ppp_start_xmit(struct sk_buff *skb, struct net_device *ndev)
*/ */
skb = ippp_ccp_compress(mlp->ccp, skb, &proto); skb = ippp_ccp_compress(mlp->ccp, skb, &proto);
if (ipt->debug & 0x24) if (ipppd->debug & 0x24)
printk(KERN_DEBUG "xmit2 skb, len %d, proto %04x\n", (int) skb->len, proto); printk(KERN_DEBUG "xmit2 skb, len %d, proto %04x\n", (int) skb->len, proto);
#ifdef CONFIG_ISDN_MPP #ifdef CONFIG_ISDN_MPP
...@@ -1297,21 +1268,17 @@ isdn_ppp_start_xmit(struct sk_buff *skb, struct net_device *ndev) ...@@ -1297,21 +1268,17 @@ isdn_ppp_start_xmit(struct sk_buff *skb, struct net_device *ndev)
isdn_ppp_push_header(idev, skb, proto); isdn_ppp_push_header(idev, skb, proto);
if (ipts->debug & 0x40) { if (ipppd->debug & 0x40) {
printk(KERN_DEBUG "skb xmit: len: %d\n", (int) skb->len); printk(KERN_DEBUG "skb xmit: len: %d\n", (int) skb->len);
isdn_ppp_frame_log("xmit", skb->data, skb->len, 32,ipt->unit,idev->ppp_slot); isdn_ppp_frame_log("xmit", skb->data, skb->len, 32, ipppd->unit, -1);
} }
isdn_net_writebuf_skb(idev, skb); isdn_net_writebuf_skb(idev, skb);
ipppd_put(ipt); out:
put:
ipppd_put(ipts);
return 0; return 0;
err_put: stop:
ipppd_put(ipts);
err:
netif_stop_queue(ndev); netif_stop_queue(ndev);
return 1; return 1;
} }
...@@ -1963,29 +1930,21 @@ isdn_ppp_hangup_slave(char *name) ...@@ -1963,29 +1930,21 @@ isdn_ppp_hangup_slave(char *name)
static void isdn_ppp_dev_kick_up(void *priv) static void isdn_ppp_dev_kick_up(void *priv)
{ {
isdn_net_dev *idev = priv; isdn_net_dev *idev = priv;
struct ipppd *ipppd = ipppd_get(idev->ppp_slot);
if (!ipppd) ipppd_queue_read(idev->ipppd, PPP_COMPFRAG, NULL, 0);
return;
ipppd_queue_read(ipppd, PPP_COMPFRAG, NULL, 0);
ipppd_put(ipppd);
} }
static void isdn_ppp_lp_kick_up(void *priv) static void isdn_ppp_lp_kick_up(void *priv)
{ {
isdn_net_local *lp = priv; isdn_net_local *lp = priv;
isdn_net_dev *idev; isdn_net_dev *idev;
struct ipppd *ipppd;
if (list_empty(&lp->online)) { if (list_empty(&lp->online)) {
isdn_BUG(); isdn_BUG();
return; return;
} }
idev = list_entry(lp->online.next, isdn_net_dev, online); idev = list_entry(lp->online.next, isdn_net_dev, online);
ipppd = ipppd_get(idev->ppp_slot); ipppd_queue_read(idev->ipppd, PPP_COMP, NULL, 0);
ipppd_queue_read(ipppd, PPP_COMP, NULL, 0);
ipppd_put(ipppd);
} }
/* Send a CCP Reset-Request or Reset-Ack directly from the kernel. */ /* Send a CCP Reset-Request or Reset-Ack directly from the kernel. */
...@@ -2186,10 +2145,10 @@ struct isdn_netif_ops isdn_ppp_ops = { ...@@ -2186,10 +2145,10 @@ struct isdn_netif_ops isdn_ppp_ops = {
.flags = IFF_NOARP | IFF_POINTOPOINT, .flags = IFF_NOARP | IFF_POINTOPOINT,
.type = ARPHRD_PPP, .type = ARPHRD_PPP,
.receive = isdn_ppp_receive, .receive = isdn_ppp_receive,
.connected = isdn_ppp_wakeup_daemon, .connected = isdn_ppp_connected,
.disconnected = isdn_ppp_disconnected, .disconnected = isdn_ppp_disconnected,
.bind = isdn_ppp_bind, .bind = isdn_ppp_bind,
.unbind = isdn_ppp_free, .unbind = isdn_ppp_unbind,
.open = isdn_ppp_open, .open = isdn_ppp_open,
.close = isdn_ppp_close, .close = isdn_ppp_close,
}; };
...@@ -410,7 +410,7 @@ typedef struct isdn_net_dev_s { ...@@ -410,7 +410,7 @@ typedef struct isdn_net_dev_s {
int chargeint; /* Interval between charge-infos */ int chargeint; /* Interval between charge-infos */
int pppbind; /* ippp device for bindings */ int pppbind; /* ippp device for bindings */
int ppp_slot; /* PPPD device slot number */ struct ipppd *ipppd; /* /dev/ipppX which controls us */
struct sk_buff_head super_tx_queue; /* List of supervisory frames to */ struct sk_buff_head super_tx_queue; /* List of supervisory frames to */
/* be transmitted asap */ /* be transmitted asap */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment