Commit a1dfdb3b authored by Kai Germaschewski's avatar Kai Germaschewski

ISDN: Alloc isdn_net_dev and struct net_device separately

This a big patch, which now mostly finishes the separation work
of isdn_net_dev, isdn_net_local and struct net_device.
The latter two are allocated per network-layer known network interface,
while isdn_net_dev is the entity which is accessed using isdnctrl,
i.e. a per-channel thing.

Since we allow for channel bundling, isdn_net_local, the priv data of
an ISDN network interface, gets a list of isdn_net_dev's which can be
used for transfering data on that interface.
parent 4b99dcc3
...@@ -24,9 +24,8 @@ ...@@ -24,9 +24,8 @@
* CISCO HDLC keepalive specific stuff * CISCO HDLC keepalive specific stuff
*/ */
static struct sk_buff* static struct sk_buff*
isdn_net_ciscohdlck_alloc_skb(isdn_net_local *lp, int len) isdn_net_ciscohdlck_alloc_skb(isdn_net_dev *idev, int len)
{ {
isdn_net_dev *idev = lp->netdev;
unsigned short hl = isdn_slot_hdrlen(idev->isdn_slot); unsigned short hl = isdn_slot_hdrlen(idev->isdn_slot);
struct sk_buff *skb; struct sk_buff *skb;
...@@ -43,62 +42,59 @@ isdn_net_ciscohdlck_alloc_skb(isdn_net_local *lp, int len) ...@@ -43,62 +42,59 @@ isdn_net_ciscohdlck_alloc_skb(isdn_net_local *lp, int len)
static int static int
isdn_ciscohdlck_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) isdn_ciscohdlck_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{ {
isdn_net_local *lp = (isdn_net_local *) dev->priv; isdn_net_local *mlp = dev->priv;
isdn_net_dev *idev = lp->netdev;
unsigned long len = 0; unsigned long len = 0;
unsigned long expires = 0; int period;
int tmp = 0; char debserint;
int period = lp->cisco_keepalive_period;
char debserint = lp->cisco_debserint;
int rc = 0; int rc = 0;
if (lp->p_encap != ISDN_NET_ENCAP_CISCOHDLCK) if (mlp->p_encap != ISDN_NET_ENCAP_CISCOHDLCK)
return -EINVAL; return -EINVAL;
switch (cmd) { switch (cmd) {
/* get/set keepalive period */ /* get/set keepalive period */
case SIOCGKEEPPERIOD: case SIOCGKEEPPERIOD:
len = (unsigned long)sizeof(lp->cisco_keepalive_period); len = sizeof(mlp->cisco_keepalive_period);
if (copy_to_user((char *)ifr->ifr_ifru.ifru_data, if (copy_to_user((char *)ifr->ifr_ifru.ifru_data,
(int *)&lp->cisco_keepalive_period, len)) (char *)&mlp->cisco_keepalive_period, len))
rc = -EFAULT; rc = -EFAULT;
break; break;
case SIOCSKEEPPERIOD: case SIOCSKEEPPERIOD:
tmp = lp->cisco_keepalive_period; len = sizeof(mlp->cisco_keepalive_period);
len = (unsigned long)sizeof(lp->cisco_keepalive_period); if (copy_from_user((char *)&period,
if (copy_from_user((int *)&period, (char *)ifr->ifr_ifru.ifru_data, len)) {
(char *)ifr->ifr_ifru.ifru_data, len))
rc = -EFAULT; rc = -EFAULT;
if ((period > 0) && (period <= 32767)) break;
lp->cisco_keepalive_period = period; }
else if (period <= 0 || period > 32767) {
rc = -EINVAL; rc = -EINVAL;
if (!rc && (tmp != lp->cisco_keepalive_period)) { break;
expires = (unsigned long)(jiffies +
lp->cisco_keepalive_period * HZ);
mod_timer(&lp->cisco_timer, expires);
printk(KERN_INFO "%s: Keepalive period set "
"to %d seconds.\n",
idev->name, lp->cisco_keepalive_period);
} }
mod_timer(&mlp->cisco_timer, jiffies + period * HZ);
printk(KERN_INFO "%s: Keepalive period set "
"to %d seconds.\n", dev->name, period);
mlp->cisco_keepalive_period = period;
break; break;
/* get/set debugging */ /* get/set debugging */
case SIOCGDEBSERINT: case SIOCGDEBSERINT:
len = (unsigned long)sizeof(lp->cisco_debserint); len = sizeof(mlp->cisco_debserint);
if (copy_to_user((char *)ifr->ifr_ifru.ifru_data, if (copy_to_user((char *)ifr->ifr_ifru.ifru_data,
(char *)&lp->cisco_debserint, len)) (char *)&mlp->cisco_debserint, len))
rc = -EFAULT; rc = -EFAULT;
break; break;
case SIOCSDEBSERINT: case SIOCSDEBSERINT:
len = (unsigned long)sizeof(lp->cisco_debserint); len = sizeof(mlp->cisco_debserint);
if (copy_from_user((char *)&debserint, if (copy_from_user((char *)&debserint,
(char *)ifr->ifr_ifru.ifru_data, len)) (char *)ifr->ifr_ifru.ifru_data, len)) {
rc = -EFAULT; rc = -EFAULT;
if ((debserint >= 0) && (debserint <= 64)) break;
lp->cisco_debserint = debserint; }
else if (debserint < 0 || debserint > 64) {
rc = -EINVAL; rc = -EINVAL;
break;
}
mlp->cisco_debserint = debserint;
break; break;
default: default:
...@@ -112,42 +108,47 @@ isdn_ciscohdlck_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) ...@@ -112,42 +108,47 @@ isdn_ciscohdlck_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
static void static void
isdn_net_ciscohdlck_slarp_send_keepalive(unsigned long data) isdn_net_ciscohdlck_slarp_send_keepalive(unsigned long data)
{ {
isdn_net_local *lp = (isdn_net_local *) data; isdn_net_local *mlp = (isdn_net_local *) data;
isdn_net_dev *idev = lp->netdev; isdn_net_dev *idev;
struct sk_buff *skb; struct sk_buff *skb;
unsigned char *p; unsigned char *p;
unsigned long last_cisco_myseq = lp->cisco_myseq; unsigned long last_cisco_myseq = mlp->cisco_myseq;
int myseq_diff = 0; int myseq_diff = 0;
lp->cisco_myseq++; if (list_empty(&mlp->online)) {
isdn_BUG();
return;
}
idev = list_entry(mlp->online.next, isdn_net_dev, online);
mlp->cisco_myseq++;
myseq_diff = (lp->cisco_myseq - lp->cisco_mineseen); myseq_diff = (mlp->cisco_myseq - mlp->cisco_mineseen);
if ((lp->cisco_line_state) && ((myseq_diff >= 3)||(myseq_diff <= -3))) { if (mlp->cisco_line_state && (myseq_diff >= 3 || myseq_diff <= -3)) {
/* line up -> down */ /* line up -> down */
lp->cisco_line_state = 0; mlp->cisco_line_state = 0;
printk (KERN_WARNING printk (KERN_WARNING
"UPDOWN: Line protocol on Interface %s," "UPDOWN: Line protocol on Interface %s,"
" changed state to down\n", idev->name); " changed state to down\n", idev->name);
/* should stop routing higher-level data accross */ /* should stop routing higher-level data accross */
} else if ((!lp->cisco_line_state) && } else if (!mlp->cisco_line_state &&
(myseq_diff >= 0) && (myseq_diff <= 2)) { myseq_diff >= 0 && myseq_diff <= 2) {
/* line down -> up */ /* line down -> up */
lp->cisco_line_state = 1; mlp->cisco_line_state = 1;
printk (KERN_WARNING printk (KERN_WARNING
"UPDOWN: Line protocol on Interface %s," "UPDOWN: Line protocol on Interface %s,"
" changed state to up\n", idev->name); " changed state to up\n", idev->name);
/* restart routing higher-level data accross */ /* restart routing higher-level data accross */
} }
if (lp->cisco_debserint) if (mlp->cisco_debserint)
printk (KERN_DEBUG "%s: HDLC " printk (KERN_DEBUG "%s: HDLC "
"myseq %lu, mineseen %lu%c, yourseen %lu, %s\n", "myseq %lu, mineseen %lu%c, yourseen %lu, %s\n",
idev->name, last_cisco_myseq, lp->cisco_mineseen, idev->name, last_cisco_myseq, mlp->cisco_mineseen,
(last_cisco_myseq == lp->cisco_mineseen) ? '*' : 040, (last_cisco_myseq == mlp->cisco_mineseen) ? '*' : 040,
lp->cisco_yourseq, mlp->cisco_yourseq,
(lp->cisco_line_state) ? "line up" : "line down"); (mlp->cisco_line_state) ? "line up" : "line down");
skb = isdn_net_ciscohdlck_alloc_skb(lp, 4 + 14); skb = isdn_net_ciscohdlck_alloc_skb(idev, 4 + 14);
if (!skb) if (!skb)
return; return;
...@@ -160,25 +161,29 @@ isdn_net_ciscohdlck_slarp_send_keepalive(unsigned long data) ...@@ -160,25 +161,29 @@ isdn_net_ciscohdlck_slarp_send_keepalive(unsigned long data)
/* slarp keepalive */ /* slarp keepalive */
p += put_u32(p, CISCO_SLARP_KEEPALIVE); p += put_u32(p, CISCO_SLARP_KEEPALIVE);
p += put_u32(p, lp->cisco_myseq); p += put_u32(p, mlp->cisco_myseq);
p += put_u32(p, lp->cisco_yourseq); p += put_u32(p, mlp->cisco_yourseq);
p += put_u16(p, 0xffff); // reliablity, always 0xffff p += put_u16(p, 0xffff); // reliablity, always 0xffff
isdn_net_write_super(idev, skb); isdn_net_write_super(idev, skb);
lp->cisco_timer.expires = jiffies + lp->cisco_keepalive_period * HZ; mod_timer(&mlp->cisco_timer, jiffies + mlp->cisco_keepalive_period * HZ);
add_timer(&lp->cisco_timer);
} }
static void static void
isdn_net_ciscohdlck_slarp_send_request(isdn_net_local *lp) isdn_net_ciscohdlck_slarp_send_request(isdn_net_local *mlp)
{ {
isdn_net_dev *idev = lp->netdev; isdn_net_dev *idev;
struct sk_buff *skb; struct sk_buff *skb;
unsigned char *p; unsigned char *p;
skb = isdn_net_ciscohdlck_alloc_skb(lp, 4 + 14); if (list_empty(&mlp->online)) {
isdn_BUG();
return;
}
idev = list_entry(mlp->online.next, isdn_net_dev, online);
skb = isdn_net_ciscohdlck_alloc_skb(idev, 4 + 14);
if (!skb) if (!skb)
return; return;
...@@ -199,8 +204,10 @@ isdn_net_ciscohdlck_slarp_send_request(isdn_net_local *lp) ...@@ -199,8 +204,10 @@ isdn_net_ciscohdlck_slarp_send_request(isdn_net_local *lp)
} }
static void static void
isdn_ciscohdlck_connected(isdn_net_local *lp) isdn_ciscohdlck_connected(isdn_net_dev *idev)
{ {
isdn_net_local *lp = idev->mlp;
lp->cisco_myseq = 0; lp->cisco_myseq = 0;
lp->cisco_mineseen = 0; lp->cisco_mineseen = 0;
lp->cisco_yourseq = 0; lp->cisco_yourseq = 0;
...@@ -219,28 +226,30 @@ isdn_ciscohdlck_connected(isdn_net_local *lp) ...@@ -219,28 +226,30 @@ isdn_ciscohdlck_connected(isdn_net_local *lp)
lp->cisco_timer.expires = jiffies + lp->cisco_keepalive_period * HZ; lp->cisco_timer.expires = jiffies + lp->cisco_keepalive_period * HZ;
add_timer(&lp->cisco_timer); add_timer(&lp->cisco_timer);
} }
isdn_net_dev_wake_queue(lp->netdev); netif_wake_queue(&lp->dev);
} }
static void static void
isdn_ciscohdlck_disconnected(isdn_net_local *lp) isdn_ciscohdlck_disconnected(isdn_net_dev *idev)
{ {
isdn_net_local *lp = idev->mlp;
if (lp->p_encap == ISDN_NET_ENCAP_CISCOHDLCK) { if (lp->p_encap == ISDN_NET_ENCAP_CISCOHDLCK) {
del_timer(&lp->cisco_timer); del_timer(&lp->cisco_timer);
} }
} }
static void static void
isdn_net_ciscohdlck_slarp_send_reply(isdn_net_local *lp) isdn_net_ciscohdlck_slarp_send_reply(isdn_net_dev *idev)
{ {
isdn_net_dev *idev = lp->netdev; isdn_net_local *mlp = idev->mlp;
struct sk_buff *skb; struct sk_buff *skb;
unsigned char *p; unsigned char *p;
struct in_device *in_dev = NULL; struct in_device *in_dev = NULL;
u32 addr = 0; /* local ipv4 address */ u32 addr = 0; /* local ipv4 address */
u32 mask = 0; /* local netmask */ u32 mask = 0; /* local netmask */
if ((in_dev = lp->dev.ip_ptr) != NULL) { if ((in_dev = mlp->dev.ip_ptr) != NULL) {
/* take primary(first) address of interface */ /* take primary(first) address of interface */
struct in_ifaddr *ifa = in_dev->ifa_list; struct in_ifaddr *ifa = in_dev->ifa_list;
if (ifa != NULL) { if (ifa != NULL) {
...@@ -249,7 +258,7 @@ isdn_net_ciscohdlck_slarp_send_reply(isdn_net_local *lp) ...@@ -249,7 +258,7 @@ isdn_net_ciscohdlck_slarp_send_reply(isdn_net_local *lp)
} }
} }
skb = isdn_net_ciscohdlck_alloc_skb(lp, 4 + 14); skb = isdn_net_ciscohdlck_alloc_skb(idev, 4 + 14);
if (!skb) if (!skb)
return; return;
...@@ -271,9 +280,9 @@ isdn_net_ciscohdlck_slarp_send_reply(isdn_net_local *lp) ...@@ -271,9 +280,9 @@ isdn_net_ciscohdlck_slarp_send_reply(isdn_net_local *lp)
} }
static void static void
isdn_net_ciscohdlck_slarp_in(isdn_net_local *lp, struct sk_buff *skb) isdn_net_ciscohdlck_slarp_in(isdn_net_dev *idev, struct sk_buff *skb)
{ {
isdn_net_dev *idev = lp->netdev; isdn_net_local *mlp = idev->mlp;
unsigned char *p; unsigned char *p;
int period; int period;
u32 code; u32 code;
...@@ -290,8 +299,8 @@ isdn_net_ciscohdlck_slarp_in(isdn_net_local *lp, struct sk_buff *skb) ...@@ -290,8 +299,8 @@ isdn_net_ciscohdlck_slarp_in(isdn_net_local *lp, struct sk_buff *skb)
switch (code) { switch (code) {
case CISCO_SLARP_REQUEST: case CISCO_SLARP_REQUEST:
lp->cisco_yourseq = 0; mlp->cisco_yourseq = 0;
isdn_net_ciscohdlck_slarp_send_reply(lp); isdn_net_ciscohdlck_slarp_send_reply(idev);
break; break;
case CISCO_SLARP_REPLY: case CISCO_SLARP_REPLY:
addr = ntohl(*(u32 *)p); addr = ntohl(*(u32 *)p);
...@@ -317,21 +326,21 @@ isdn_net_ciscohdlck_slarp_in(isdn_net_local *lp, struct sk_buff *skb) ...@@ -317,21 +326,21 @@ isdn_net_ciscohdlck_slarp_in(isdn_net_local *lp, struct sk_buff *skb)
HIPQUAD(addr), HIPQUAD(mask)); HIPQUAD(addr), HIPQUAD(mask));
break; break;
case CISCO_SLARP_KEEPALIVE: case CISCO_SLARP_KEEPALIVE:
period = (int)((jiffies - lp->cisco_last_slarp_in period = (int)((jiffies - mlp->cisco_last_slarp_in
+ HZ/2 - 1) / HZ); + HZ/2 - 1) / HZ);
if (lp->cisco_debserint && if (mlp->cisco_debserint &&
(period != lp->cisco_keepalive_period) && (period != mlp->cisco_keepalive_period) &&
lp->cisco_last_slarp_in) { mlp->cisco_last_slarp_in) {
printk(KERN_DEBUG "%s: Keepalive period mismatch - " printk(KERN_DEBUG "%s: Keepalive period mismatch - "
"is %d but should be %d.\n", "is %d but should be %d.\n",
idev->name, period, lp->cisco_keepalive_period); idev->name, period, mlp->cisco_keepalive_period);
} }
lp->cisco_last_slarp_in = jiffies; mlp->cisco_last_slarp_in = jiffies;
p += get_u32(p, &my_seq); p += get_u32(p, &my_seq);
p += get_u32(p, &your_seq); p += get_u32(p, &your_seq);
p += get_u16(p, &unused); p += get_u16(p, &unused);
lp->cisco_yourseq = my_seq; mlp->cisco_yourseq = my_seq;
lp->cisco_mineseen = your_seq; mlp->cisco_mineseen = your_seq;
break; break;
} }
} }
...@@ -363,7 +372,7 @@ isdn_ciscohdlck_receive(isdn_net_local *lp, isdn_net_dev *idev, ...@@ -363,7 +372,7 @@ isdn_ciscohdlck_receive(isdn_net_local *lp, isdn_net_dev *idev,
switch (type) { switch (type) {
case CISCO_TYPE_SLARP: case CISCO_TYPE_SLARP:
isdn_net_ciscohdlck_slarp_in(lp, skb); isdn_net_ciscohdlck_slarp_in(idev, skb);
goto out_free; goto out_free;
case CISCO_TYPE_CDP: case CISCO_TYPE_CDP:
if (lp->cisco_debserint) if (lp->cisco_debserint)
...@@ -372,7 +381,7 @@ isdn_ciscohdlck_receive(isdn_net_local *lp, isdn_net_dev *idev, ...@@ -372,7 +381,7 @@ isdn_ciscohdlck_receive(isdn_net_local *lp, isdn_net_dev *idev,
goto out_free; goto out_free;
default: default:
/* no special cisco protocol */ /* no special cisco protocol */
isdn_net_reset_huptimer(lp, idev); idev->huptimer = 0;
skb->protocol = htons(type); skb->protocol = htons(type);
netif_rx(skb); netif_rx(skb);
return; return;
......
...@@ -508,7 +508,7 @@ isdn_status_callback(isdn_ctrl * c) ...@@ -508,7 +508,7 @@ isdn_status_callback(isdn_ctrl * c)
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->isdn_slot == i) { if (p->isdn_slot == i) {
strcpy(cmd.parm.setup.eazmsn, p->local.msn); strcpy(cmd.parm.setup.eazmsn, p->mlp->msn);
isdn_slot_command(i, ISDN_CMD_ACCEPTD, &cmd); isdn_slot_command(i, ISDN_CMD_ACCEPTD, &cmd);
retval = 1; retval = 1;
break; break;
......
...@@ -22,11 +22,11 @@ ...@@ -22,11 +22,11 @@
#undef ISDN_DEBUG_MODEM_DUMP #undef ISDN_DEBUG_MODEM_DUMP
#undef ISDN_DEBUG_MODEM_VOICE #undef ISDN_DEBUG_MODEM_VOICE
#undef ISDN_DEBUG_AT #undef ISDN_DEBUG_AT
#undef ISDN_DEBUG_NET_DUMP #define ISDN_DEBUG_NET_DUMP
#undef ISDN_DEBUG_NET_DIAL #define ISDN_DEBUG_NET_DIAL
#undef ISDN_DEBUG_NET_ICALL #define ISDN_DEBUG_NET_ICALL
#undef ISDN_DEBUG_STATCALLB #define ISDN_DEBUG_STATCALLB
#undef ISDN_DEBUG_COMMAND #define ISDN_DEBUG_COMMAND
#ifdef ISDN_DEBUG_NET_DIAL #ifdef ISDN_DEBUG_NET_DIAL
#define dbg_net_dial(arg...) printk(KERN_DEBUG arg) #define dbg_net_dial(arg...) printk(KERN_DEBUG arg)
......
...@@ -90,32 +90,20 @@ LIST_HEAD(isdn_net_devs); /* Linked list of isdn_net_dev's */ ...@@ -90,32 +90,20 @@ LIST_HEAD(isdn_net_devs); /* Linked list of isdn_net_dev's */
/* /*
* Find out if the netdevice has been ifup-ed yet. * Find out if the netdevice has been ifup-ed yet.
* For slaves, look at the corresponding master.
*/ */
static inline int static inline int
isdn_net_device_started(isdn_net_dev *idev) isdn_net_device_started(isdn_net_dev *idev)
{ {
struct net_device *dev; return netif_running(&idev->mlp->dev);
if (idev->master)
dev = &idev->master->dev;
else
dev = &idev->local.dev;
return netif_running(dev);
} }
/* /*
* stop the network -> net_device queue. * stop the network -> net_device queue.
* For slaves, stop the corresponding master interface.
*/ */
static inline void static inline void
isdn_net_dev_stop_queue(isdn_net_dev *idev) isdn_net_dev_stop_queue(isdn_net_dev *idev)
{ {
if (idev->master) netif_stop_queue(&idev->mlp->dev);
netif_stop_queue(&idev->master->dev);
else
netif_stop_queue(&idev->local.dev);
} }
/* /*
...@@ -126,18 +114,13 @@ isdn_net_dev_stop_queue(isdn_net_dev *idev) ...@@ -126,18 +114,13 @@ isdn_net_dev_stop_queue(isdn_net_dev *idev)
static inline int static inline int
isdn_net_device_busy(isdn_net_dev *idev) isdn_net_device_busy(isdn_net_dev *idev)
{ {
isdn_net_local *mlp; isdn_net_local *mlp = idev->mlp;
unsigned long flags; unsigned long flags;
int retval = 1; int retval = 1;
if (!isdn_net_dev_busy(idev)) if (!isdn_net_dev_busy(idev))
return 0; return 0;
if (idev->master)
mlp = idev->master;
else
mlp = &idev->local;
spin_lock_irqsave(&mlp->online_lock, flags); spin_lock_irqsave(&mlp->online_lock, flags);
list_for_each_entry(idev, &mlp->online, online) { list_for_each_entry(idev, &mlp->online, online) {
if (!isdn_net_dev_busy(idev)) { if (!isdn_net_dev_busy(idev)) {
...@@ -212,9 +195,9 @@ int isdn_net_online(isdn_net_dev *idev) ...@@ -212,9 +195,9 @@ int isdn_net_online(isdn_net_dev *idev)
static int isdn_net_force_dial_idev(isdn_net_dev *); static int isdn_net_force_dial_idev(isdn_net_dev *);
static int isdn_net_start_xmit(struct sk_buff *, struct net_device *); static int isdn_net_start_xmit(struct sk_buff *, struct net_device *);
static void do_dialout(isdn_net_local *lp); static void do_dialout(isdn_net_dev *idev);
static int isdn_net_set_encap(isdn_net_dev *p, int encap); static int isdn_net_handle_event(isdn_net_dev *idev, int pr, void *arg);
static int isdn_net_handle_event(isdn_net_local *lp, int pr, void *arg); static int isdn_net_set_encap(isdn_net_local *mlp, int encap);
char *isdn_net_revision = "$Revision: 1.140.6.11 $"; char *isdn_net_revision = "$Revision: 1.140.6.11 $";
...@@ -260,32 +243,30 @@ isdn_net_open(struct net_device *dev) ...@@ -260,32 +243,30 @@ isdn_net_open(struct net_device *dev)
* unbind a net-interface (resets interface after an error) * unbind a net-interface (resets interface after an error)
*/ */
static void static void
isdn_net_unbind_channel(isdn_net_local * lp) isdn_net_unbind_channel(isdn_net_dev *idev)
{ {
isdn_net_dev *idev = lp->netdev; isdn_net_local *mlp = idev->mlp;
ulong flags; ulong flags;
save_flags(flags); save_flags(flags);
cli(); cli();
if (lp->ops->unbind) if (idev->isdn_slot < 0) {
lp->ops->unbind(lp); isdn_BUG();
return;
}
if (mlp->ops->unbind)
mlp->ops->unbind(idev);
skb_queue_purge(&idev->super_tx_queue); skb_queue_purge(&idev->super_tx_queue);
if (!idev->master) { /* reset only master device */
/* Moral equivalent of dev_purge_queues():
BEWARE! This chunk of code cannot be called from hardware
interrupt handler. I hope it is true. --ANK
*/
qdisc_reset(lp->dev.qdisc);
}
idev->dialstate = ST_NULL; idev->dialstate = ST_NULL;
if (idev->isdn_slot >= 0) {
isdn_slot_set_rx_netdev(idev->isdn_slot, NULL); isdn_slot_set_rx_netdev(idev->isdn_slot, NULL);
isdn_slot_set_st_netdev(idev->isdn_slot, NULL); isdn_slot_set_st_netdev(idev->isdn_slot, NULL);
isdn_slot_free(idev->isdn_slot, ISDN_USAGE_NET); isdn_slot_free(idev->isdn_slot, ISDN_USAGE_NET);
}
idev->isdn_slot = -1; idev->isdn_slot = -1;
restore_flags(flags); restore_flags(flags);
...@@ -295,9 +276,9 @@ isdn_net_unbind_channel(isdn_net_local * lp) ...@@ -295,9 +276,9 @@ isdn_net_unbind_channel(isdn_net_local * lp)
* Assign an ISDN-channel to a net-interface * Assign an ISDN-channel to a net-interface
*/ */
static int static int
isdn_net_bind_channel(isdn_net_local *lp, int idx) isdn_net_bind_channel(isdn_net_dev *idev, int idx)
{ {
isdn_net_dev *idev = lp->netdev; isdn_net_local *mlp = idev->mlp;
int retval = 0; int retval = 0;
unsigned long flags; unsigned long flags;
...@@ -305,14 +286,14 @@ isdn_net_bind_channel(isdn_net_local *lp, int idx) ...@@ -305,14 +286,14 @@ isdn_net_bind_channel(isdn_net_local *lp, int idx)
cli(); cli();
idev->isdn_slot = idx; idev->isdn_slot = idx;
isdn_slot_set_rx_netdev(idev->isdn_slot, lp->netdev); isdn_slot_set_rx_netdev(idev->isdn_slot, idev);
isdn_slot_set_st_netdev(idev->isdn_slot, lp->netdev); isdn_slot_set_st_netdev(idev->isdn_slot, idev);
if (lp->ops->bind) if (mlp->ops->bind)
retval = lp->ops->bind(lp); retval = mlp->ops->bind(idev);
if (retval < 0) if (retval < 0)
isdn_net_unbind_channel(lp); isdn_net_unbind_channel(idev);
restore_flags(flags); restore_flags(flags);
return retval; return retval;
...@@ -331,7 +312,7 @@ isdn_net_bind_channel(isdn_net_local *lp, int idx) ...@@ -331,7 +312,7 @@ isdn_net_bind_channel(isdn_net_local *lp, int idx)
static void isdn_net_hup_timer(unsigned long data) static void isdn_net_hup_timer(unsigned long data)
{ {
isdn_net_dev *idev = (isdn_net_dev *) data; isdn_net_dev *idev = (isdn_net_dev *) data;
isdn_net_local *lp = &idev->local; isdn_net_local *mlp = idev->mlp;
if (!isdn_net_online(idev)) { if (!isdn_net_online(idev)) {
isdn_BUG(); isdn_BUG();
...@@ -339,38 +320,38 @@ static void isdn_net_hup_timer(unsigned long data) ...@@ -339,38 +320,38 @@ static void isdn_net_hup_timer(unsigned long data)
} }
dbg_net_dial("%s: huptimer %d, onhtime %d, chargetime %ld, chargeint %d\n", dbg_net_dial("%s: huptimer %d, onhtime %d, chargetime %ld, chargeint %d\n",
l->name, l->huptimer, l->onhtime, l->chargetime, l->chargeint); idev->name, idev->huptimer, mlp->onhtime, idev->chargetime, idev->chargeint);
if (lp->onhtime == 0) if (mlp->onhtime == 0)
return; return;
if (idev->huptimer++ <= lp->onhtime) if (idev->huptimer++ <= mlp->onhtime)
goto mod_timer; goto mod_timer;
if ((lp->hupflags & (ISDN_MANCHARGE | ISDN_CHARGEHUP)) == (ISDN_MANCHARGE | ISDN_CHARGEHUP)) { if ((mlp->hupflags & (ISDN_MANCHARGE | ISDN_CHARGEHUP)) == (ISDN_MANCHARGE | ISDN_CHARGEHUP)) {
while (time_after(jiffies, idev->chargetime + idev->chargeint)) while (time_after(jiffies, idev->chargetime + idev->chargeint))
idev->chargetime += idev->chargeint; idev->chargetime += idev->chargeint;
if (time_after(jiffies, idev->chargetime + idev->chargeint - 2 * HZ)) { if (time_after(jiffies, idev->chargetime + idev->chargeint - 2 * HZ)) {
if (idev->outgoing || lp->hupflags & ISDN_INHUP) { if (idev->outgoing || mlp->hupflags & ISDN_INHUP) {
isdn_net_hangup(idev); isdn_net_hangup(idev);
return; return;
} }
} }
} else if (idev->outgoing) { } else if (idev->outgoing) {
if (lp->hupflags & ISDN_CHARGEHUP) { if (mlp->hupflags & ISDN_CHARGEHUP) {
if (idev->charge_state != ST_CHARGE_HAVE_CINT) { if (idev->charge_state != ST_CHARGE_HAVE_CINT) {
dbg_net_dial("%s: did not get CINT\n", lp->name); dbg_net_dial("%s: did not get CINT\n", idev->name);
isdn_net_hangup(idev); isdn_net_hangup(idev);
return; return;
} else if (time_after(jiffies, idev->chargetime + idev->chargeint)) { } else if (time_after(jiffies, idev->chargetime + idev->chargeint)) {
dbg_net_dial("%s: chtime = %lu, chint = %d\n", dbg_net_dial("%s: chtime = %lu, chint = %d\n",
lp->name, lp->chargetime, lp->chargeint); idev->name, idev->chargetime, idev->chargeint);
isdn_net_hangup(idev); isdn_net_hangup(idev);
return; return;
} }
} }
} else if (lp->hupflags & ISDN_INHUP) { } else if (mlp->hupflags & ISDN_INHUP) {
isdn_net_hangup(idev); isdn_net_hangup(idev);
return; return;
} }
...@@ -385,22 +366,15 @@ static void isdn_net_lp_disconnected(isdn_net_dev *idev) ...@@ -385,22 +366,15 @@ static void isdn_net_lp_disconnected(isdn_net_dev *idev)
static void isdn_net_connected(isdn_net_dev *idev) static void isdn_net_connected(isdn_net_dev *idev)
{ {
isdn_net_local *lp = &idev->local; isdn_net_local *mlp = idev->mlp;
idev->dialstate = ST_ACTIVE; idev->dialstate = ST_ACTIVE;
idev->hup_timer.expires = jiffies + HZ; idev->hup_timer.expires = jiffies + HZ;
add_timer(&idev->hup_timer); add_timer(&idev->hup_timer);
if (lp->p_encap != ISDN_NET_ENCAP_SYNCPPP) { if (mlp->p_encap != ISDN_NET_ENCAP_SYNCPPP)
isdn_net_local *mlp;
if (idev->master)
mlp = idev->master;
else
mlp = &idev->local;
isdn_net_add_to_bundle(mlp, idev); isdn_net_add_to_bundle(mlp, idev);
}
printk(KERN_INFO "isdn_net: %s connected\n", idev->name); printk(KERN_INFO "isdn_net: %s connected\n", idev->name);
/* If first Chargeinfo comes before B-Channel connect, /* If first Chargeinfo comes before B-Channel connect,
* we correct the timestamp here. * we correct the timestamp here.
...@@ -415,8 +389,8 @@ static void isdn_net_connected(isdn_net_dev *idev) ...@@ -415,8 +389,8 @@ static void isdn_net_connected(isdn_net_dev *idev)
idev->cps = 0; idev->cps = 0;
idev->last_jiffies = jiffies; idev->last_jiffies = jiffies;
if (lp->ops->connected) if (mlp->ops->connected)
lp->ops->connected(lp); mlp->ops->connected(idev);
else else
isdn_net_dev_wake_queue(idev); isdn_net_dev_wake_queue(idev);
} }
...@@ -430,17 +404,14 @@ static void isdn_net_connected(isdn_net_dev *idev) ...@@ -430,17 +404,14 @@ static void isdn_net_connected(isdn_net_dev *idev)
int int
isdn_net_stat_callback(int idx, isdn_ctrl *c) isdn_net_stat_callback(int idx, isdn_ctrl *c)
{ {
isdn_net_dev *p = isdn_slot_st_netdev(idx); isdn_net_dev *idev = isdn_slot_st_netdev(idx);
isdn_net_local *lp;
int cmd = c->command;
if (!p) { if (!idev) {
HERE; HERE;
return 0; return 0;
} }
lp = &p->local;
return isdn_net_handle_event(lp, cmd, c); return isdn_net_handle_event(idev, c->command, c);
} }
static void static void
...@@ -448,27 +419,27 @@ isdn_net_dial_timer(unsigned long data) ...@@ -448,27 +419,27 @@ isdn_net_dial_timer(unsigned long data)
{ {
isdn_net_dev *idev = (isdn_net_dev *) data; isdn_net_dev *idev = (isdn_net_dev *) data;
isdn_net_handle_event(&idev->local, idev->dial_event, NULL); isdn_net_handle_event(idev, idev->dial_event, NULL);
} }
/* Initiate dialout. Set phone-number-pointer to first number /* Initiate dialout. Set phone-number-pointer to first number
* of interface. * of interface.
*/ */
static void static void
init_dialout(isdn_net_local *lp) init_dialout(isdn_net_dev *idev)
{ {
isdn_net_dev *idev = lp->netdev; isdn_net_local *mlp = idev->mlp;
idev->dial = 0; idev->dial = 0;
if (lp->dialtimeout > 0 && if (mlp->dialtimeout > 0 &&
(idev->dialstarted == 0 || (idev->dialstarted == 0 ||
time_after(jiffies, idev->dialstarted + lp->dialtimeout + lp->dialwait))) { time_after(jiffies, idev->dialstarted + mlp->dialtimeout + mlp->dialwait))) {
idev->dialstarted = jiffies; idev->dialstarted = jiffies;
idev->dialwait_timer = 0; idev->dialwait_timer = 0;
} }
lp->dialretry = 0; idev->dialretry = 0;
do_dialout(lp); do_dialout(idev);
} }
/* Setup interface, dial current phone-number, switch to next number. /* Setup interface, dial current phone-number, switch to next number.
...@@ -476,54 +447,54 @@ init_dialout(isdn_net_local *lp) ...@@ -476,54 +447,54 @@ init_dialout(isdn_net_local *lp)
* retry-counter. * retry-counter.
*/ */
static void static void
do_dialout(isdn_net_local *lp) do_dialout(isdn_net_dev *idev)
{ {
isdn_net_dev *idev = lp->netdev; isdn_net_local *mlp = idev->mlp;
int i; int i;
unsigned long flags; unsigned long flags;
struct isdn_net_phone *phone; struct isdn_net_phone *phone;
struct dial_info dial = { struct dial_info dial = {
.l2_proto = lp->l2_proto, .l2_proto = mlp->l2_proto,
.l3_proto = lp->l3_proto, .l3_proto = mlp->l3_proto,
.si1 = 7, .si1 = 7,
.si2 = 0, .si2 = 0,
.msn = lp->msn, .msn = mlp->msn,
}; };
if (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF) if (ISDN_NET_DIALMODE(*mlp) == ISDN_NET_DM_OFF)
return; return;
spin_lock_irqsave(&lp->lock, flags); spin_lock_irqsave(&mlp->lock, flags);
if (list_empty(&lp->phone[1])) { if (list_empty(&mlp->phone[1])) {
spin_unlock_irqrestore(&lp->lock, flags); spin_unlock_irqrestore(&mlp->lock, flags);
return; return;
} }
i = 0; i = 0;
list_for_each_entry(phone, &lp->phone[1], list) { list_for_each_entry(phone, &mlp->phone[1], list) {
if (i++ == idev->dial) if (i++ == idev->dial)
goto found; goto found;
} }
/* otherwise start in front */ /* otherwise start in front */
phone = list_entry(lp->phone[1].next, struct isdn_net_phone, list); phone = list_entry(mlp->phone[1].next, struct isdn_net_phone, list);
idev->dial = 0; idev->dial = 0;
lp->dialretry++; idev->dialretry++;
found: found:
idev->dial++; idev->dial++;
dial.phone = phone->num; dial.phone = phone->num;
spin_unlock_irqrestore(&lp->lock, flags); spin_unlock_irqrestore(&mlp->lock, flags);
if (lp->dialretry > lp->dialmax) { if (idev->dialretry > mlp->dialmax) {
if (lp->dialtimeout == 0) { if (mlp->dialtimeout == 0) {
idev->dialwait_timer = jiffies + lp->dialwait; idev->dialwait_timer = jiffies + mlp->dialwait;
idev->dialstarted = 0; idev->dialstarted = 0;
} }
isdn_net_hangup(idev); isdn_net_hangup(idev);
return; return;
} }
if(lp->dialtimeout > 0 && if (mlp->dialtimeout > 0 &&
time_after(jiffies, idev->dialstarted + lp->dialtimeout)) { time_after(jiffies, idev->dialstarted + mlp->dialtimeout)) {
idev->dialwait_timer = jiffies + lp->dialwait; idev->dialwait_timer = jiffies + mlp->dialwait;
idev->dialstarted = 0; idev->dialstarted = 0;
isdn_net_hangup(idev); isdn_net_hangup(idev);
return; return;
...@@ -540,8 +511,8 @@ do_dialout(isdn_net_local *lp) ...@@ -540,8 +511,8 @@ do_dialout(isdn_net_local *lp)
else else
idev->charge_state = ST_CHARGE_NULL; idev->charge_state = ST_CHARGE_NULL;
if (lp->cbdelay && (lp->flags & ISDN_NET_CBOUT)) { if (mlp->cbdelay && (mlp->flags & ISDN_NET_CBOUT)) {
idev->dial_timer.expires = jiffies + lp->cbdelay; idev->dial_timer.expires = jiffies + mlp->cbdelay;
idev->dial_event = EV_NET_TIMER_CB; idev->dial_event = EV_NET_TIMER_CB;
} else { } else {
idev->dial_timer.expires = jiffies + 10 * HZ; idev->dial_timer.expires = jiffies + 10 * HZ;
...@@ -555,13 +526,14 @@ do_dialout(isdn_net_local *lp) ...@@ -555,13 +526,14 @@ do_dialout(isdn_net_local *lp)
* For ISDN_STAT_*, returns 1 if event was for us * For ISDN_STAT_*, returns 1 if event was for us
*/ */
static int static int
isdn_net_handle_event(isdn_net_local *lp, int pr, void *arg) isdn_net_handle_event(isdn_net_dev *idev, int pr, void *arg)
{ {
isdn_net_dev *idev = lp->netdev; isdn_net_local *mlp = idev->mlp;
isdn_ctrl *c = arg; isdn_ctrl *c = arg;
isdn_ctrl cmd; isdn_ctrl cmd;
dbg_net_dial("%s: dialstate=%d pr=%#x\n", lp->name, lp->dialstate,pr); dbg_net_dial("%s: dialstate=%d pr=%#x\n", idev->name,
idev->dialstate, pr);
switch (idev->dialstate) { switch (idev->dialstate) {
case ST_ACTIVE: case ST_ACTIVE:
...@@ -569,19 +541,19 @@ isdn_net_handle_event(isdn_net_local *lp, int pr, void *arg) ...@@ -569,19 +541,19 @@ isdn_net_handle_event(isdn_net_local *lp, int pr, void *arg)
case ISDN_STAT_BSENT: case ISDN_STAT_BSENT:
/* A packet has successfully been sent out */ /* A packet has successfully been sent out */
isdn_net_dec_frame_cnt(idev); isdn_net_dec_frame_cnt(idev);
lp->stats.tx_packets++; mlp->stats.tx_packets++;
lp->stats.tx_bytes += c->parm.length; mlp->stats.tx_bytes += c->parm.length;
return 1; return 1;
case ISDN_STAT_DHUP: case ISDN_STAT_DHUP:
if (lp->ops->disconnected) if (mlp->ops->disconnected)
lp->ops->disconnected(lp); mlp->ops->disconnected(idev);
isdn_net_lp_disconnected(idev); isdn_net_lp_disconnected(idev);
isdn_slot_all_eaz(idev->isdn_slot); isdn_slot_all_eaz(idev->isdn_slot);
printk(KERN_INFO "%s: remote hangup\n", idev->name); printk(KERN_INFO "%s: remote hangup\n", idev->name);
printk(KERN_INFO "%s: Chargesum is %d\n", idev->name, printk(KERN_INFO "%s: Chargesum is %d\n", idev->name,
idev->charge); idev->charge);
isdn_net_unbind_channel(lp); isdn_net_unbind_channel(idev);
return 1; return 1;
case ISDN_STAT_CINF: case ISDN_STAT_CINF:
/* Charge-info from TelCo. Calculate interval between /* Charge-info from TelCo. Calculate interval between
...@@ -601,7 +573,7 @@ isdn_net_handle_event(isdn_net_local *lp, int pr, void *arg) ...@@ -601,7 +573,7 @@ isdn_net_handle_event(isdn_net_local *lp, int pr, void *arg)
break; break;
} }
idev->chargetime = jiffies; idev->chargetime = jiffies;
dbg_net_dial("%s: got CINF\n", lp->name); dbg_net_dial("%s: got CINF\n", idev->name);
return 1; return 1;
} }
break; break;
...@@ -609,7 +581,7 @@ isdn_net_handle_event(isdn_net_local *lp, int pr, void *arg) ...@@ -609,7 +581,7 @@ isdn_net_handle_event(isdn_net_local *lp, int pr, void *arg)
switch (pr) { switch (pr) {
case EV_NET_TIMER_OUT_DCONN: case EV_NET_TIMER_OUT_DCONN:
/* try again */ /* try again */
do_dialout(lp); do_dialout(idev);
return 1; return 1;
case EV_NET_TIMER_CB: case EV_NET_TIMER_CB:
/* Remote does callback. Hangup after cbdelay, /* Remote does callback. Hangup after cbdelay,
...@@ -630,7 +602,7 @@ isdn_net_handle_event(isdn_net_local *lp, int pr, void *arg) ...@@ -630,7 +602,7 @@ isdn_net_handle_event(isdn_net_local *lp, int pr, void *arg)
del_timer(&idev->dial_timer); del_timer(&idev->dial_timer);
isdn_slot_all_eaz(idev->isdn_slot); isdn_slot_all_eaz(idev->isdn_slot);
printk(KERN_INFO "%s: remote hangup\n", idev->name); printk(KERN_INFO "%s: remote hangup\n", idev->name);
isdn_net_unbind_channel(lp); isdn_net_unbind_channel(idev);
return 1; return 1;
} }
break; break;
...@@ -638,7 +610,7 @@ isdn_net_handle_event(isdn_net_local *lp, int pr, void *arg) ...@@ -638,7 +610,7 @@ isdn_net_handle_event(isdn_net_local *lp, int pr, void *arg)
switch (pr) { switch (pr) {
case EV_NET_TIMER_OUT_BCONN: case EV_NET_TIMER_OUT_BCONN:
/* try again */ /* try again */
do_dialout(lp); do_dialout(idev);
return 1; return 1;
case ISDN_STAT_BCONN: case ISDN_STAT_BCONN:
del_timer(&idev->dial_timer); del_timer(&idev->dial_timer);
...@@ -649,7 +621,7 @@ isdn_net_handle_event(isdn_net_local *lp, int pr, void *arg) ...@@ -649,7 +621,7 @@ isdn_net_handle_event(isdn_net_local *lp, int pr, void *arg)
del_timer(&idev->dial_timer); del_timer(&idev->dial_timer);
isdn_slot_all_eaz(idev->isdn_slot); isdn_slot_all_eaz(idev->isdn_slot);
printk(KERN_INFO "%s: remote hangup\n", idev->name); printk(KERN_INFO "%s: remote hangup\n", idev->name);
isdn_net_unbind_channel(lp); isdn_net_unbind_channel(idev);
return 1; return 1;
} }
break; break;
...@@ -670,7 +642,7 @@ isdn_net_handle_event(isdn_net_local *lp, int pr, void *arg) ...@@ -670,7 +642,7 @@ isdn_net_handle_event(isdn_net_local *lp, int pr, void *arg)
del_timer(&idev->dial_timer); del_timer(&idev->dial_timer);
isdn_slot_all_eaz(idev->isdn_slot); isdn_slot_all_eaz(idev->isdn_slot);
printk(KERN_INFO "%s: remote hangup\n", idev->name); printk(KERN_INFO "%s: remote hangup\n", idev->name);
isdn_net_unbind_channel(lp); isdn_net_unbind_channel(idev);
return 1; return 1;
} }
break; break;
...@@ -688,7 +660,7 @@ isdn_net_handle_event(isdn_net_local *lp, int pr, void *arg) ...@@ -688,7 +660,7 @@ isdn_net_handle_event(isdn_net_local *lp, int pr, void *arg)
del_timer(&idev->dial_timer); del_timer(&idev->dial_timer);
isdn_slot_all_eaz(idev->isdn_slot); isdn_slot_all_eaz(idev->isdn_slot);
printk(KERN_INFO "%s: remote hangup\n", idev->name); printk(KERN_INFO "%s: remote hangup\n", idev->name);
isdn_net_unbind_channel(lp); isdn_net_unbind_channel(idev);
return 1; return 1;
} }
break; break;
...@@ -696,7 +668,7 @@ isdn_net_handle_event(isdn_net_local *lp, int pr, void *arg) ...@@ -696,7 +668,7 @@ isdn_net_handle_event(isdn_net_local *lp, int pr, void *arg)
switch (pr) { switch (pr) {
case EV_NET_TIMER_CB: case EV_NET_TIMER_CB:
/* Callback Delay */ /* Callback Delay */
init_dialout(lp); init_dialout(idev);
return 1; return 1;
} }
break; break;
...@@ -704,7 +676,7 @@ isdn_net_handle_event(isdn_net_local *lp, int pr, void *arg) ...@@ -704,7 +676,7 @@ isdn_net_handle_event(isdn_net_local *lp, int pr, void *arg)
isdn_BUG(); isdn_BUG();
break; break;
} }
printk("NOT HANDLED?\n"); isdn_BUG();
return 0; return 0;
} }
...@@ -714,7 +686,7 @@ isdn_net_handle_event(isdn_net_local *lp, int pr, void *arg) ...@@ -714,7 +686,7 @@ isdn_net_handle_event(isdn_net_local *lp, int pr, void *arg)
void void
isdn_net_hangup(isdn_net_dev *idev) isdn_net_hangup(isdn_net_dev *idev)
{ {
isdn_net_local *lp = &idev->local; isdn_net_local *mlp = idev->mlp;
isdn_ctrl cmd; isdn_ctrl cmd;
del_timer_sync(&idev->hup_timer); del_timer_sync(&idev->hup_timer);
...@@ -732,15 +704,15 @@ isdn_net_hangup(isdn_net_dev *idev) ...@@ -732,15 +704,15 @@ isdn_net_hangup(isdn_net_dev *idev)
} }
} }
printk(KERN_INFO "isdn_net: local hangup %s\n", idev->name); printk(KERN_INFO "isdn_net: local hangup %s\n", idev->name);
if (lp->ops->disconnected) if (mlp->ops->disconnected)
lp->ops->disconnected(lp); mlp->ops->disconnected(idev);
isdn_net_lp_disconnected(idev); isdn_net_lp_disconnected(idev);
isdn_slot_command(idev->isdn_slot, ISDN_CMD_HANGUP, &cmd); isdn_slot_command(idev->isdn_slot, ISDN_CMD_HANGUP, &cmd);
printk(KERN_INFO "%s: Chargesum is %d\n", idev->name, idev->charge); printk(KERN_INFO "%s: Chargesum is %d\n", idev->name, idev->charge);
isdn_slot_all_eaz(idev->isdn_slot); isdn_slot_all_eaz(idev->isdn_slot);
isdn_net_unbind_channel(lp); isdn_net_unbind_channel(idev);
} }
void void
...@@ -760,9 +732,10 @@ typedef struct { ...@@ -760,9 +732,10 @@ typedef struct {
} ip_ports; } ip_ports;
static void static void
isdn_net_log_skb(struct sk_buff * skb, isdn_net_local * lp) isdn_net_log_skb(struct sk_buff *skb, isdn_net_dev *idev)
{ {
isdn_net_dev *idev = lp->netdev; isdn_net_local *mlp = idev->mlp;
u_char *p = skb->nh.raw; /* hopefully, this was set correctly */ u_char *p = skb->nh.raw; /* hopefully, this was set correctly */
unsigned short proto = ntohs(skb->protocol); unsigned short proto = ntohs(skb->protocol);
int data_ofs; int data_ofs;
...@@ -778,7 +751,7 @@ isdn_net_log_skb(struct sk_buff * skb, isdn_net_local * lp) ...@@ -778,7 +751,7 @@ isdn_net_log_skb(struct sk_buff * skb, isdn_net_local * lp)
printk(KERN_DEBUG "isdn_net: protocol %04x is buggy, dev %s\n", skb->protocol, idev->name); printk(KERN_DEBUG "isdn_net: protocol %04x is buggy, dev %s\n", skb->protocol, idev->name);
p = buf; p = buf;
proto = ETH_P_IP; proto = ETH_P_IP;
switch (lp->p_encap) { switch (mlp->p_encap) {
case ISDN_NET_ENCAP_IPTYP: case ISDN_NET_ENCAP_IPTYP:
proto = ntohs(*(unsigned short *) &buf[0]); proto = ntohs(*(unsigned short *) &buf[0]);
p = &buf[2]; p = &buf[2];
...@@ -892,7 +865,7 @@ static void isdn_net_tasklet(unsigned long data) ...@@ -892,7 +865,7 @@ static void isdn_net_tasklet(unsigned long data)
*/ */
void isdn_net_writebuf_skb(isdn_net_dev *idev, struct sk_buff *skb) void isdn_net_writebuf_skb(isdn_net_dev *idev, struct sk_buff *skb)
{ {
isdn_net_local *lp = &idev->local; isdn_net_local *mlp = idev->mlp;
int ret; int ret;
int len = skb->len; /* save len */ int len = skb->len; /* save len */
...@@ -920,7 +893,7 @@ void isdn_net_writebuf_skb(isdn_net_dev *idev, struct sk_buff *skb) ...@@ -920,7 +893,7 @@ void isdn_net_writebuf_skb(isdn_net_dev *idev, struct sk_buff *skb)
error: error:
dev_kfree_skb(skb); dev_kfree_skb(skb);
lp->stats.tx_errors++; mlp->stats.tx_errors++;
} }
...@@ -938,24 +911,21 @@ void isdn_net_writebuf_skb(isdn_net_dev *idev, struct sk_buff *skb) ...@@ -938,24 +911,21 @@ void isdn_net_writebuf_skb(isdn_net_dev *idev, struct sk_buff *skb)
static int static int
isdn_net_xmit(struct net_device *ndev, struct sk_buff *skb) isdn_net_xmit(struct net_device *ndev, struct sk_buff *skb)
{ {
isdn_net_local *mlp; isdn_net_dev *idev, *sdev;
isdn_net_dev *sdev; isdn_net_local *mlp = ndev->priv;
isdn_net_local *lp = ndev->priv;
isdn_net_dev *idev = lp->netdev;
int retv = 0; int retv = 0;
mlp = ndev->priv;
/* For the other encaps the header has already been built */ /* For the other encaps the header has already been built */
if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) { if (mlp->p_encap == ISDN_NET_ENCAP_SYNCPPP) {
return isdn_ppp_xmit(skb, ndev); return isdn_ppp_xmit(skb, ndev);
} }
mlp = ndev->priv;
idev = isdn_net_get_locked_dev(mlp); idev = isdn_net_get_locked_dev(mlp);
if (!idev) { if (!idev) {
printk(KERN_WARNING "%s: all channels busy - requeuing!\n", ndev->name); printk(KERN_WARNING "%s: all channels busy - requeuing!\n", ndev->name);
return 1; return 1;
} }
/* we have our idev locked from now on */ /* we have our idev locked from now on */
lp = &idev->local;
/* Reset hangup-timeout */ /* Reset hangup-timeout */
idev->huptimer = 0; // FIXME? idev->huptimer = 0; // FIXME?
...@@ -975,7 +945,7 @@ isdn_net_xmit(struct net_device *ndev, struct sk_buff *skb) ...@@ -975,7 +945,7 @@ isdn_net_xmit(struct net_device *ndev, struct sk_buff *skb)
if (dev->net_verbose > 3) if (dev->net_verbose > 3)
printk(KERN_DEBUG "%s: %d bogocps\n", idev->name, idev->cps); printk(KERN_DEBUG "%s: %d bogocps\n", idev->name, idev->cps);
if (idev->cps > lp->triggercps) { if (idev->cps > mlp->triggercps) {
if (idev->slave) { if (idev->slave) {
if (!idev->sqfull) { if (!idev->sqfull) {
/* First time overload: set timestamp only */ /* First time overload: set timestamp only */
...@@ -983,7 +953,7 @@ isdn_net_xmit(struct net_device *ndev, struct sk_buff *skb) ...@@ -983,7 +953,7 @@ isdn_net_xmit(struct net_device *ndev, struct sk_buff *skb)
idev->sqfull_stamp = jiffies; idev->sqfull_stamp = jiffies;
} else { } else {
/* subsequent overload: if slavedelay exceeded, start dialing */ /* subsequent overload: if slavedelay exceeded, start dialing */
if (time_after(jiffies, idev->sqfull_stamp + lp->slavedelay)) { if (time_after(jiffies, idev->sqfull_stamp + mlp->slavedelay)) {
sdev = idev->slave; sdev = idev->slave;
if (!isdn_net_bound(sdev)) { if (!isdn_net_bound(sdev)) {
isdn_net_force_dial_idev(sdev); isdn_net_force_dial_idev(sdev);
...@@ -992,12 +962,12 @@ isdn_net_xmit(struct net_device *ndev, struct sk_buff *skb) ...@@ -992,12 +962,12 @@ isdn_net_xmit(struct net_device *ndev, struct sk_buff *skb)
} }
} }
} else { } else {
if (idev->sqfull && time_after(jiffies, idev->sqfull_stamp + lp->slavedelay + 10 * HZ)) { if (idev->sqfull && time_after(jiffies, idev->sqfull_stamp + mlp->slavedelay + 10 * HZ)) {
idev->sqfull = 0; idev->sqfull = 0;
} }
/* this is a hack to allow auto-hangup for slaves on moderate loads */ /* this is a hack to allow auto-hangup for slaves on moderate loads */
list_del(&mlp->online); list_del(&mlp->online);
list_add_tail(&mlp->online, &lp->netdev->online); list_add_tail(&mlp->online, &idev->online);
} }
return retv; return retv;
...@@ -1020,29 +990,32 @@ isdn_net_adjust_hdr(struct sk_buff *skb, struct net_device *dev) ...@@ -1020,29 +990,32 @@ isdn_net_adjust_hdr(struct sk_buff *skb, struct net_device *dev)
} }
void isdn_net_tx_timeout(struct net_device * ndev) void isdn_net_tx_timeout(struct net_device *dev)
{ {
isdn_net_local *lp = ndev->priv; printk(KERN_WARNING "isdn_tx_timeout dev %s\n", dev->name);
isdn_net_dev *idev = lp->netdev;
printk(KERN_WARNING "isdn_tx_timeout dev %s %d\n",
ndev->name, idev->dialstate);
netif_wake_queue(ndev); netif_wake_queue(dev);
} }
static int static int
isdn_net_autodial(struct sk_buff *skb, struct net_device *ndev) isdn_net_autodial(struct sk_buff *skb, struct net_device *ndev)
{ {
isdn_net_local *lp = ndev->priv; isdn_net_local *mlp = ndev->priv;
isdn_net_dev *idev = lp->netdev; isdn_net_dev *idev = list_entry(mlp->slaves.next, isdn_net_dev, slaves);
if (!(ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_AUTO)) /* are we dialing already? */
if (isdn_net_bound(idev)) {
netif_stop_queue(ndev);
return 1;
}
if (ISDN_NET_DIALMODE(*mlp) != ISDN_NET_DM_AUTO)
goto discard; goto discard;
if (idev->dialwait_timer <= 0) if (idev->dialwait_timer <= 0)
if (idev->dialstarted > 0 && lp->dialtimeout > 0 && time_before(jiffies, idev->dialstarted + lp->dialtimeout + lp->dialwait)) if (idev->dialstarted > 0 && mlp->dialtimeout > 0 &&
idev->dialwait_timer = idev->dialstarted + lp->dialtimeout + lp->dialwait; time_before(jiffies, idev->dialstarted + mlp->dialtimeout + mlp->dialwait))
idev->dialwait_timer = idev->dialstarted + mlp->dialtimeout + mlp->dialwait;
if (idev->dialwait_timer > 0) { if (idev->dialwait_timer > 0) {
if(time_before(jiffies, idev->dialwait_timer)) if(time_before(jiffies, idev->dialwait_timer))
...@@ -1056,7 +1029,7 @@ isdn_net_autodial(struct sk_buff *skb, struct net_device *ndev) ...@@ -1056,7 +1029,7 @@ isdn_net_autodial(struct sk_buff *skb, struct net_device *ndev)
/* Log packet, which triggered dialing */ /* Log packet, which triggered dialing */
if (dev->net_verbose) if (dev->net_verbose)
isdn_net_log_skb(skb, lp); isdn_net_log_skb(skb, idev);
netif_stop_queue(ndev); netif_stop_queue(ndev);
return 1; return 1;
...@@ -1076,27 +1049,22 @@ isdn_net_autodial(struct sk_buff *skb, struct net_device *ndev) ...@@ -1076,27 +1049,22 @@ isdn_net_autodial(struct sk_buff *skb, struct net_device *ndev)
static int static int
isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev) isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
{ {
isdn_net_local *lp = ndev->priv; isdn_net_local *mlp = ndev->priv;
isdn_net_dev *idev = lp->netdev;
int retval; int retval;
if (lp->p_encap == ISDN_NET_ENCAP_X25IFACE) if (mlp->p_encap == ISDN_NET_ENCAP_X25IFACE)
return isdn_x25_start_xmit(skb, ndev); return isdn_x25_start_xmit(skb, ndev);
/* auto-dialing xmit function */ /* auto-dialing xmit function */
isdn_net_adjust_hdr(skb, ndev); isdn_net_adjust_hdr(skb, ndev);
isdn_dumppkt("S:", skb->data, skb->len, 40); isdn_dumppkt("S:", skb->data, skb->len, 40);
if (!isdn_net_bound(idev)) if (list_empty(&mlp->online))
return isdn_net_autodial(skb, ndev); return isdn_net_autodial(skb, ndev);
/* Device is bound to an ISDN channel */ /* Device is bound to an ISDN channel */
ndev->trans_start = jiffies; ndev->trans_start = jiffies;
if (idev->dialstate != ST_ACTIVE) {
netif_stop_queue(ndev);
return 1;
}
/* ISDN connection is established, try sending */ /* ISDN connection is established, try sending */
retval = isdn_net_xmit(ndev, skb); retval = isdn_net_xmit(ndev, skb);
if (retval) if (retval)
...@@ -1111,19 +1079,19 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev) ...@@ -1111,19 +1079,19 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
static int static int
isdn_net_close(struct net_device *dev) isdn_net_close(struct net_device *dev)
{ {
isdn_net_local *lp = dev->priv; isdn_net_local *mlp = dev->priv;
isdn_net_dev *idev = lp->netdev; struct list_head *l, *n;
isdn_net_dev *sdev; isdn_net_dev *sdev;
if (lp->ops->close) if (mlp->ops->close)
lp->ops->close(lp); mlp->ops->close(mlp);
netif_stop_queue(dev); netif_stop_queue(dev);
for (sdev = idev->slave; sdev; sdev = sdev->slave)
isdn_net_hangup(sdev);
isdn_net_hangup(idev); list_for_each_safe(l, n, &mlp->online) {
sdev = list_entry(l, isdn_net_dev, online);
isdn_net_hangup(sdev);
}
isdn_MOD_DEC_USE_COUNT(); isdn_MOD_DEC_USE_COUNT();
return 0; return 0;
} }
...@@ -1144,27 +1112,18 @@ isdn_net_get_stats(struct net_device *dev) ...@@ -1144,27 +1112,18 @@ isdn_net_get_stats(struct net_device *dev)
static void static void
isdn_net_receive(isdn_net_dev *idev, struct sk_buff *skb) isdn_net_receive(isdn_net_dev *idev, struct sk_buff *skb)
{ {
isdn_net_local *lp; isdn_net_local *mlp = idev->mlp;
struct net_device *ndev;
idev->transcount += skb->len; idev->transcount += skb->len;
if (idev->master) {
/* Bundling: If device is a slave-device, deliver to master, also mlp->stats.rx_packets++;
* handle master's statistics and hangup-timeout mlp->stats.rx_bytes += skb->len;
*/ skb->dev = &mlp->dev;
ndev = &idev->master->dev;
} else {
ndev = &idev->local.dev;
}
lp = ndev->priv;
lp->stats.rx_packets++;
lp->stats.rx_bytes += skb->len;
skb->dev = ndev;
skb->pkt_type = PACKET_HOST; skb->pkt_type = PACKET_HOST;
skb->mac.raw = skb->data; skb->mac.raw = skb->data;
isdn_dumppkt("R:", skb->data, skb->len, 40); isdn_dumppkt("R:", skb->data, skb->len, 40);
lp->ops->receive(lp, idev, skb); mlp->ops->receive(mlp, idev, skb);
} }
/* /*
...@@ -1207,16 +1166,16 @@ isdn_net_init(struct net_device *ndev) ...@@ -1207,16 +1166,16 @@ isdn_net_init(struct net_device *ndev)
} }
static int static int
isdn_net_do_callback(isdn_net_local *lp) isdn_net_do_callback(isdn_net_dev *idev)
{ {
isdn_net_dev *idev = lp->netdev; isdn_net_local *mlp = idev->mlp;
int slot; int slot;
/* /*
* Is the state MANUAL? * Is the state MANUAL?
* If so, no callback can be made, * If so, no callback can be made,
* so reject actively. * so reject actively.
*/ */
if (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF) { if (ISDN_NET_DIALMODE(*mlp) == ISDN_NET_DM_OFF) {
printk(KERN_INFO "incoming call for callback, interface %s `off' -> rejected\n", printk(KERN_INFO "incoming call for callback, interface %s `off' -> rejected\n",
idev->name); idev->name);
return 3; return 3;
...@@ -1224,22 +1183,22 @@ isdn_net_do_callback(isdn_net_local *lp) ...@@ -1224,22 +1183,22 @@ isdn_net_do_callback(isdn_net_local *lp)
printk(KERN_DEBUG "%s: start callback\n", idev->name); printk(KERN_DEBUG "%s: start callback\n", idev->name);
/* Grab a free ISDN-Channel */ /* Grab a free ISDN-Channel */
slot = isdn_get_free_slot(ISDN_USAGE_NET, lp->l2_proto, lp->l3_proto, slot = isdn_get_free_slot(ISDN_USAGE_NET, mlp->l2_proto, mlp->l3_proto,
idev->pre_device, idev->pre_channel, lp->msn); idev->pre_device, idev->pre_channel, mlp->msn);
if (slot < 0) if (slot < 0)
goto err; goto err;
if (isdn_net_bind_channel(lp, slot) < 0) if (isdn_net_bind_channel(idev, slot) < 0)
goto err; goto err;
/* Setup dialstate. */ /* Setup dialstate. */
idev->dial_timer.expires = jiffies + lp->cbdelay; idev->dial_timer.expires = jiffies + mlp->cbdelay;
idev->dial_event = EV_NET_TIMER_CB; idev->dial_event = EV_NET_TIMER_CB;
add_timer(&idev->dial_timer); add_timer(&idev->dial_timer);
idev->dialstate = ST_WAIT_BEFORE_CB; idev->dialstate = ST_WAIT_BEFORE_CB;
/* Initiate dialing by returning 2 or 4 */ /* Initiate dialing by returning 2 or 4 */
return (lp->flags & ISDN_NET_CBHUP) ? 2 : 4; return (mlp->flags & ISDN_NET_CBHUP) ? 2 : 4;
err: err:
return 0; return 0;
...@@ -1267,12 +1226,12 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup) ...@@ -1267,12 +1226,12 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup)
char *eaz; char *eaz;
unsigned char si1, si2; unsigned char si1, si2;
int match_more = 0; int match_more = 0;
int retval;
struct list_head *l; struct list_head *l;
struct isdn_net_phone *n; struct isdn_net_phone *n;
ulong flags; ulong flags;
char nr[32]; char nr[32];
char *my_eaz; char *my_eaz;
int retval;
isdn_ctrl cmd; isdn_ctrl cmd;
int slot = isdn_dc2minor(di, ch); int slot = isdn_dc2minor(di, ch);
...@@ -1311,13 +1270,13 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup) ...@@ -1311,13 +1270,13 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup)
list_for_each(l, &isdn_net_devs) { list_for_each(l, &isdn_net_devs) {
isdn_net_dev *idev = list_entry(l, isdn_net_dev, global_list); isdn_net_dev *idev = list_entry(l, isdn_net_dev, global_list);
isdn_net_local *lp = &idev->local; isdn_net_local *mlp = idev->mlp;
/* check acceptable call types for DOV */ /* check acceptable call types for DOV */
dbg_net_icall("n_fi: if='%s', l.msn=%s, l.flags=%d, l.dstate=%d\n", dbg_net_icall("n_fi: if='%s', l.msn=%s, l.flags=%#x, l.dstate=%d\n",
lp->name, lp->msn, lp->flags, lp->dialstate); idev->name, mlp->msn, mlp->flags, idev->dialstate);
my_eaz = isdn_slot_map_eaz2msn(slot, lp->msn); my_eaz = isdn_slot_map_eaz2msn(slot, mlp->msn);
if (si1 == 1) { /* it's a DOV call, check if we allow it */ if (si1 == 1) { /* it's a DOV call, check if we allow it */
if (*my_eaz == 'v' || *my_eaz == 'V' || if (*my_eaz == 'v' || *my_eaz == 'V' ||
*my_eaz == 'b' || *my_eaz == 'B') *my_eaz == 'b' || *my_eaz == 'B')
...@@ -1344,7 +1303,7 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup) ...@@ -1344,7 +1303,7 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup)
continue; continue;
dbg_net_icall("n_fi: match1, pdev=%d pch=%d\n", dbg_net_icall("n_fi: match1, pdev=%d pch=%d\n",
lp->pre_device, lp->pre_channel); idev->pre_device, idev->pre_channel);
if (isdn_slot_usage(idx) & ISDN_USAGE_EXCLUSIVE && if (isdn_slot_usage(idx) & ISDN_USAGE_EXCLUSIVE &&
(idev->pre_channel != ch || idev->pre_device != di)) { (idev->pre_channel != ch || idev->pre_device != di)) {
...@@ -1352,15 +1311,15 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup) ...@@ -1352,15 +1311,15 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup)
continue; continue;
} }
dbg_net_icall("n_fi: match2\n"); dbg_net_icall("n_fi: match2\n");
if (lp->flags & ISDN_NET_SECURE) { if (mlp->flags & ISDN_NET_SECURE) {
spin_lock_irqsave(&lp->lock, flags); spin_lock_irqsave(&mlp->lock, flags);
list_for_each_entry(n, &lp->phone[0], list) { list_for_each_entry(n, &mlp->phone[0], list) {
if (!isdn_msncmp(nr, n->num)) { if (!isdn_msncmp(nr, n->num)) {
spin_unlock_irqrestore(&lp->lock, flags); spin_unlock_irqrestore(&mlp->lock, flags);
goto found; goto found;
} }
} }
spin_unlock_irqrestore(&lp->lock, flags); spin_unlock_irqrestore(&mlp->lock, flags);
continue; continue;
} }
found: found:
...@@ -1372,7 +1331,7 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup) ...@@ -1372,7 +1331,7 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup)
* If so, no dialin is allowed, * If so, no dialin is allowed,
* so reject actively. * so reject actively.
* */ * */
if (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF) { if (ISDN_NET_DIALMODE(*mlp) == ISDN_NET_DM_OFF) {
restore_flags(flags); restore_flags(flags);
printk(KERN_INFO "incoming call, interface %s `stopped' -> rejected\n", printk(KERN_INFO "incoming call, interface %s `stopped' -> rejected\n",
idev->name); idev->name);
...@@ -1388,41 +1347,18 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup) ...@@ -1388,41 +1347,18 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup)
idev->name); idev->name);
return 3; return 3;
} }
/* Interface is up, now see if it's a slave. If so, see if if (mlp->flags & ISDN_NET_CALLBACK) {
* it's master and parent slave is online. If not, reject the call. retval = isdn_net_do_callback(idev);
*/ restore_flags(flags);
if (idev->master) { return retval;
isdn_net_dev *pdev = idev->master->netdev; }
printk(KERN_DEBUG "ICALLslv: %s\n", idev->name); printk(KERN_DEBUG "%s: call from %s -> %s accepted\n",
printk(KERN_DEBUG "master=%s\n", pdev->name); idev->name, nr, eaz);
if (isdn_net_bound(pdev)) {
printk(KERN_DEBUG "master online\n");
/* Master is online, find parent-slave (master if first slave) */
while (pdev->slave) {
if (pdev->slave == idev)
break;
pdev = pdev->slave;
}
} else
printk(KERN_DEBUG "master offline\n");
/* Found parent, if it's offline iterate next device */
printk(KERN_DEBUG "mlpf: %d\n", isdn_net_bound(pdev));
if (!isdn_net_bound(pdev)) {
continue;
}
}
if (lp->flags & ISDN_NET_CALLBACK) {
retval = isdn_net_do_callback(lp);
restore_flags(flags);
return retval;
}
printk(KERN_DEBUG "%s: call from %s -> %s accepted\n", idev->name,
nr, eaz);
strcpy(isdn_slot_num(idx), nr); strcpy(isdn_slot_num(idx), nr);
isdn_slot_set_usage(idx, (isdn_slot_usage(idx) & ISDN_USAGE_EXCLUSIVE) | ISDN_USAGE_NET); isdn_slot_set_usage(idx, (isdn_slot_usage(idx) & ISDN_USAGE_EXCLUSIVE) | ISDN_USAGE_NET);
isdn_net_bind_channel(lp, idx); isdn_net_bind_channel(idev, idx);
idev->outgoing = 0; idev->outgoing = 0;
idev->huptimer = 0; idev->huptimer = 0;
...@@ -1430,9 +1366,9 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup) ...@@ -1430,9 +1366,9 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup)
/* Got incoming Call, setup L2 and L3 protocols, /* Got incoming Call, setup L2 and L3 protocols,
* then wait for D-Channel-connect * then wait for D-Channel-connect
*/ */
cmd.arg = lp->l2_proto << 8; cmd.arg = mlp->l2_proto << 8;
isdn_slot_command(idev->isdn_slot, ISDN_CMD_SETL2, &cmd); isdn_slot_command(idev->isdn_slot, ISDN_CMD_SETL2, &cmd);
cmd.arg = lp->l3_proto << 8; cmd.arg = mlp->l3_proto << 8;
isdn_slot_command(idev->isdn_slot, ISDN_CMD_SETL3, &cmd); isdn_slot_command(idev->isdn_slot, ISDN_CMD_SETL3, &cmd);
idev->dial_timer.expires = jiffies + 15 * HZ; idev->dial_timer.expires = jiffies + 15 * HZ;
...@@ -1455,12 +1391,11 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup) ...@@ -1455,12 +1391,11 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup)
isdn_net_dev * isdn_net_dev *
isdn_net_findif(char *name) isdn_net_findif(char *name)
{ {
struct list_head *l; isdn_net_dev *idev;
list_for_each(l, &isdn_net_devs) { list_for_each_entry(idev, &isdn_net_devs, global_list) {
isdn_net_dev *p = list_entry(l, isdn_net_dev, global_list); if (!strcmp(idev->name, name))
if (!strcmp(p->name, name)) return idev;
return p;
} }
return NULL; return NULL;
} }
...@@ -1475,7 +1410,7 @@ isdn_net_force_dial_idev(isdn_net_dev *idev) ...@@ -1475,7 +1410,7 @@ isdn_net_force_dial_idev(isdn_net_dev *idev)
{ {
int slot; int slot;
unsigned long flags; unsigned long flags;
isdn_net_local *lp = &idev->local; isdn_net_local *mlp = idev->mlp;
if (isdn_net_bound(idev)) if (isdn_net_bound(idev))
return -EBUSY; return -EBUSY;
...@@ -1486,18 +1421,18 @@ isdn_net_force_dial_idev(isdn_net_dev *idev) ...@@ -1486,18 +1421,18 @@ isdn_net_force_dial_idev(isdn_net_dev *idev)
if (idev->exclusive >= 0) if (idev->exclusive >= 0)
slot = idev->exclusive; slot = idev->exclusive;
else else
slot = isdn_get_free_slot(ISDN_USAGE_NET, lp->l2_proto, slot = isdn_get_free_slot(ISDN_USAGE_NET, mlp->l2_proto,
lp->l3_proto, idev->pre_device, mlp->l3_proto, idev->pre_device,
idev->pre_channel, lp->msn); idev->pre_channel, mlp->msn);
if (slot < 0) if (slot < 0)
goto err; goto err;
if (isdn_net_bind_channel(lp, slot) < 0) if (isdn_net_bind_channel(idev, slot) < 0)
goto err;; goto err;;
/* Initiate dialing */ /* Initiate dialing */
restore_flags(flags); restore_flags(flags);
init_dialout(lp); init_dialout(idev);
return 0; return 0;
...@@ -1514,9 +1449,10 @@ isdn_net_force_dial_idev(isdn_net_dev *idev) ...@@ -1514,9 +1449,10 @@ isdn_net_force_dial_idev(isdn_net_dev *idev)
int int
isdn_net_dial_req(isdn_net_dev *idev) isdn_net_dial_req(isdn_net_dev *idev)
{ {
isdn_net_local *lp = &idev->local; isdn_net_local *mlp = idev->mlp;
/* is there a better error code? */ /* is there a better error code? */
if (!(ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_AUTO)) return -EBUSY; if (ISDN_NET_DIALMODE(*mlp) != ISDN_NET_DM_AUTO)
return -EBUSY;
return isdn_net_force_dial_idev(idev); return isdn_net_force_dial_idev(idev);
} }
...@@ -1540,10 +1476,9 @@ isdn_net_force_dial(char *name) ...@@ -1540,10 +1476,9 @@ isdn_net_force_dial(char *name)
* Allocate a new network-interface and initialize its data structures. * Allocate a new network-interface and initialize its data structures.
*/ */
int int
isdn_net_new(char *name, struct net_device *master) isdn_net_new(char *name, isdn_net_local *mlp)
{ {
int retval; int retval;
isdn_net_local *mlp = master->priv;
isdn_net_dev *netdev; isdn_net_dev *netdev;
/* Avoid creating an existing interface */ /* Avoid creating an existing interface */
...@@ -1551,46 +1486,62 @@ isdn_net_new(char *name, struct net_device *master) ...@@ -1551,46 +1486,62 @@ isdn_net_new(char *name, struct net_device *master)
printk(KERN_WARNING "isdn_net: interface %s already exists\n", name); printk(KERN_WARNING "isdn_net: interface %s already exists\n", name);
return -EEXIST; return -EEXIST;
} }
if (!(netdev = kmalloc(sizeof(isdn_net_dev), GFP_KERNEL))) { if (!(netdev = kmalloc(sizeof(*netdev), GFP_KERNEL))) {
printk(KERN_WARNING "isdn_net: Could not allocate net-device\n"); printk(KERN_WARNING "isdn_net: Could not allocate net-device\n");
return -ENOMEM; return -ENOMEM;
} }
memset(netdev, 0, sizeof(isdn_net_dev)); memset(netdev, 0, sizeof(*netdev));
strcpy(netdev->name, name); strcpy(netdev->name, name);
strcpy(netdev->local.dev.name, name); if (!mlp) {
netdev->local.dev.priv = &netdev->local;
netdev->local.dev.init = isdn_net_init;
if (master) {
/* Device shall be a slave */
isdn_net_dev *p = mlp->netdev;
while (p->slave)
p = p->slave;
p->slave = netdev;
} else {
/* Device shall be a master */ /* Device shall be a master */
/* mlp = kmalloc(sizeof(*mlp), GFP_KERNEL);
* Watchdog timer (currently) for master only. if (!mlp)
*/ return -ENOMEM;
netdev->local.dev.tx_timeout = isdn_net_tx_timeout;
netdev->local.dev.watchdog_timeo = ISDN_NET_TX_TIMEOUT; memset(mlp, 0, sizeof(*mlp));
retval = register_netdev(&netdev->local.dev);
mlp->magic = ISDN_NET_MAGIC;
mlp->dev.tx_timeout = isdn_net_tx_timeout;
mlp->dev.watchdog_timeo = ISDN_NET_TX_TIMEOUT;
strcpy(mlp->dev.name, name);
mlp->dev.priv = mlp;
mlp->dev.init = isdn_net_init;
INIT_LIST_HEAD(&mlp->slaves);
INIT_LIST_HEAD(&mlp->online);
spin_lock_init(&mlp->lock);
mlp->p_encap = -1;
mlp->l2_proto = ISDN_PROTO_L2_X75I;
mlp->l3_proto = ISDN_PROTO_L3_TRANS;
mlp->triggercps = 6000;
mlp->slavedelay = 10 * HZ;
mlp->hupflags = ISDN_INHUP; /* Do hangup even on incoming calls */
mlp->onhtime = 10; /* Default hangup-time for saving costs
of those who forget configuring this */
mlp->dialmax = 1;
mlp->flags = ISDN_NET_CBHUP | ISDN_NET_DM_MANUAL; /* Hangup before Callback, manual dial */
mlp->cbdelay = 5 * HZ; /* Wait 5 secs before Callback */
mlp->dialtimeout = -1; /* Infinite Dial-Timeout */
mlp->dialwait = 5 * HZ; /* Wait 5 sec. after failed dial */
spin_lock_init(&mlp->lock);
INIT_LIST_HEAD(&mlp->phone[0]);
INIT_LIST_HEAD(&mlp->phone[1]);
isdn_net_set_encap(mlp, ISDN_NET_ENCAP_RAWIP);
retval = register_netdev(&mlp->dev);
if (retval) { if (retval) {
printk(KERN_WARNING "isdn_net: Could not register net-device\n"); printk(KERN_WARNING "isdn_net: Could not register net-device\n");
kfree(netdev); kfree(netdev);
return retval; return retval;
} }
} }
netdev->local.magic = ISDN_NET_MAGIC; netdev->mlp = mlp;
list_add_tail(&netdev->slaves, &mlp->slaves);
INIT_LIST_HEAD(&netdev->local.online);
spin_lock_init(&netdev->local.online_lock);
netdev->local.netdev = netdev;
tasklet_init(&netdev->tlet, isdn_net_tasklet, (unsigned long) netdev); tasklet_init(&netdev->tlet, isdn_net_tasklet, (unsigned long) netdev);
spin_lock_init(&netdev->xmit_lock); spin_lock_init(&netdev->xmit_lock);
skb_queue_head_init(&netdev->super_tx_queue);
netdev->isdn_slot = -1; netdev->isdn_slot = -1;
netdev->pre_device = -1; netdev->pre_device = -1;
...@@ -1600,20 +1551,6 @@ isdn_net_new(char *name, struct net_device *master) ...@@ -1600,20 +1551,6 @@ isdn_net_new(char *name, struct net_device *master)
netdev->ppp_slot = -1; netdev->ppp_slot = -1;
netdev->pppbind = -1; netdev->pppbind = -1;
netdev->local.p_encap = -1;
skb_queue_head_init(&netdev->super_tx_queue);
netdev->local.l2_proto = ISDN_PROTO_L2_X75I;
netdev->local.l3_proto = ISDN_PROTO_L3_TRANS;
netdev->local.triggercps = 6000;
netdev->local.slavedelay = 10 * HZ;
netdev->local.hupflags = ISDN_INHUP; /* Do hangup even on incoming calls */
netdev->local.onhtime = 10; /* Default hangup-time for saving costs
of those who forget configuring this */
netdev->local.dialmax = 1;
netdev->local.flags = ISDN_NET_CBHUP | ISDN_NET_DM_MANUAL; /* Hangup before Callback, manual dial */
netdev->local.cbdelay = 5 * HZ; /* Wait 5 secs before Callback */
netdev->local.dialtimeout = -1; /* Infinite Dial-Timeout */
netdev->local.dialwait = 5 * HZ; /* Wait 5 sec. after failed dial */
netdev->dialstarted = 0; /* Jiffies of last dial-start */ netdev->dialstarted = 0; /* Jiffies of last dial-start */
netdev->dialwait_timer = 0; /* Jiffies of earliest next dial-start */ netdev->dialwait_timer = 0; /* Jiffies of earliest next dial-start */
...@@ -1623,10 +1560,6 @@ isdn_net_new(char *name, struct net_device *master) ...@@ -1623,10 +1560,6 @@ isdn_net_new(char *name, struct net_device *master)
init_timer(&netdev->hup_timer); init_timer(&netdev->hup_timer);
netdev->hup_timer.data = (unsigned long) netdev; netdev->hup_timer.data = (unsigned long) netdev;
netdev->hup_timer.function = isdn_net_hup_timer; netdev->hup_timer.function = isdn_net_hup_timer;
spin_lock_init(&netdev->local.lock);
INIT_LIST_HEAD(&netdev->local.phone[0]);
INIT_LIST_HEAD(&netdev->local.phone[1]);
isdn_net_set_encap(netdev, ISDN_NET_ENCAP_RAWIP);
/* Put into to netdev-chain */ /* Put into to netdev-chain */
list_add(&netdev->global_list, &isdn_net_devs); list_add(&netdev->global_list, &isdn_net_devs);
...@@ -1647,20 +1580,16 @@ isdn_net_newslave(char *parm) ...@@ -1647,20 +1580,16 @@ isdn_net_newslave(char *parm)
/* Master must already exist */ /* Master must already exist */
if (!(m = isdn_net_findif(parm))) if (!(m = isdn_net_findif(parm)))
return -ESRCH; return -ESRCH;
/* Master must be a real interface, not a slave */
if (m->master)
return -ENXIO;
/* Master must not be started yet */ /* Master must not be started yet */
if (isdn_net_device_started(m)) if (isdn_net_device_started(m))
return -EBUSY; return -EBUSY;
return isdn_net_new(p+1, &m->local.dev); return isdn_net_new(p+1, m->mlp);
} }
static int static int
isdn_net_set_encap(isdn_net_dev *idev, int encap) isdn_net_set_encap(isdn_net_local *lp, int encap)
{ {
isdn_net_local *lp = &idev->local;
int retval = 0; int retval = 0;
if (lp->p_encap == encap){ if (lp->p_encap == encap){
...@@ -1668,7 +1597,7 @@ isdn_net_set_encap(isdn_net_dev *idev, int encap) ...@@ -1668,7 +1597,7 @@ isdn_net_set_encap(isdn_net_dev *idev, int encap)
retval = 0; retval = 0;
goto out; goto out;
} }
if (isdn_net_device_started(idev)) { if (netif_running(&lp->dev)) {
retval = -EBUSY; retval = -EBUSY;
goto out; goto out;
} }
...@@ -1704,7 +1633,7 @@ isdn_net_set_encap(isdn_net_dev *idev, int encap) ...@@ -1704,7 +1633,7 @@ isdn_net_set_encap(isdn_net_dev *idev, int encap)
static int static int
isdn_net_bind(isdn_net_dev *idev, isdn_net_ioctl_cfg *cfg) isdn_net_bind(isdn_net_dev *idev, isdn_net_ioctl_cfg *cfg)
{ {
isdn_net_local *lp = &idev->local; isdn_net_local *mlp = idev->mlp;
int i, retval; int i, retval;
int drvidx = -1; int drvidx = -1;
int chidx = -1; int chidx = -1;
...@@ -1755,8 +1684,8 @@ isdn_net_bind(isdn_net_dev *idev, isdn_net_ioctl_cfg *cfg) ...@@ -1755,8 +1684,8 @@ isdn_net_bind(isdn_net_dev *idev, isdn_net_ioctl_cfg *cfg)
} }
if (cfg->exclusive) { if (cfg->exclusive) {
/* If binding is exclusive, try to grab the channel */ /* If binding is exclusive, try to grab the channel */
idev->exclusive = isdn_get_free_slot(ISDN_USAGE_NET, lp->l2_proto, idev->exclusive = isdn_get_free_slot(ISDN_USAGE_NET, mlp->l2_proto,
lp->l3_proto, drvidx, chidx, cfg->eaz); mlp->l3_proto, drvidx, chidx, cfg->eaz);
if (idev->exclusive < 0) { if (idev->exclusive < 0) {
/* Grab failed, because desired channel is in use */ /* Grab failed, because desired channel is in use */
retval = -EBUSY; retval = -EBUSY;
...@@ -1782,7 +1711,7 @@ int ...@@ -1782,7 +1711,7 @@ int
isdn_net_setcfg(isdn_net_ioctl_cfg *cfg) isdn_net_setcfg(isdn_net_ioctl_cfg *cfg)
{ {
isdn_net_dev *idev = isdn_net_findif(cfg->name); isdn_net_dev *idev = isdn_net_findif(cfg->name);
isdn_net_local *lp = &idev->local; isdn_net_local *mlp = idev->mlp;
ulong features; ulong features;
int i, retval; int i, retval;
...@@ -1804,7 +1733,7 @@ isdn_net_setcfg(isdn_net_ioctl_cfg *cfg) ...@@ -1804,7 +1733,7 @@ isdn_net_setcfg(isdn_net_ioctl_cfg *cfg)
goto out; goto out;
} }
retval = isdn_net_set_encap(idev, cfg->p_encap); retval = isdn_net_set_encap(mlp, cfg->p_encap);
if (retval) if (retval)
goto out; goto out;
...@@ -1812,64 +1741,64 @@ isdn_net_setcfg(isdn_net_ioctl_cfg *cfg) ...@@ -1812,64 +1741,64 @@ isdn_net_setcfg(isdn_net_ioctl_cfg *cfg)
if (retval) if (retval)
goto out; goto out;
strncpy(lp->msn, cfg->eaz, ISDN_MSNLEN-1); strncpy(mlp->msn, cfg->eaz, ISDN_MSNLEN-1);
lp->msn[ISDN_MSNLEN-1] = 0; mlp->msn[ISDN_MSNLEN-1] = 0;
lp->onhtime = cfg->onhtime; mlp->onhtime = cfg->onhtime;
idev->charge = cfg->charge; idev->charge = cfg->charge;
lp->l2_proto = cfg->l2_proto; mlp->l2_proto = cfg->l2_proto;
lp->l3_proto = cfg->l3_proto; mlp->l3_proto = cfg->l3_proto;
lp->cbdelay = cfg->cbdelay * HZ / 5; mlp->cbdelay = cfg->cbdelay * HZ / 5;
lp->dialmax = cfg->dialmax; mlp->dialmax = cfg->dialmax;
lp->triggercps = cfg->triggercps; mlp->triggercps = cfg->triggercps;
lp->slavedelay = cfg->slavedelay * HZ; mlp->slavedelay = cfg->slavedelay * HZ;
idev->pppbind = cfg->pppbind; idev->pppbind = cfg->pppbind;
lp->dialtimeout = cfg->dialtimeout >= 0 ? cfg->dialtimeout * HZ : -1; mlp->dialtimeout = cfg->dialtimeout >= 0 ? cfg->dialtimeout * HZ : -1;
lp->dialwait = cfg->dialwait * HZ; mlp->dialwait = cfg->dialwait * HZ;
if (cfg->secure) if (cfg->secure)
lp->flags |= ISDN_NET_SECURE; mlp->flags |= ISDN_NET_SECURE;
else else
lp->flags &= ~ISDN_NET_SECURE; mlp->flags &= ~ISDN_NET_SECURE;
if (cfg->cbhup) if (cfg->cbhup)
lp->flags |= ISDN_NET_CBHUP; mlp->flags |= ISDN_NET_CBHUP;
else else
lp->flags &= ~ISDN_NET_CBHUP; mlp->flags &= ~ISDN_NET_CBHUP;
switch (cfg->callback) { switch (cfg->callback) {
case 0: case 0:
lp->flags &= ~(ISDN_NET_CALLBACK | ISDN_NET_CBOUT); mlp->flags &= ~(ISDN_NET_CALLBACK | ISDN_NET_CBOUT);
break; break;
case 1: case 1:
lp->flags |= ISDN_NET_CALLBACK; mlp->flags |= ISDN_NET_CALLBACK;
lp->flags &= ~ISDN_NET_CBOUT; mlp->flags &= ~ISDN_NET_CBOUT;
break; break;
case 2: case 2:
lp->flags |= ISDN_NET_CBOUT; mlp->flags |= ISDN_NET_CBOUT;
lp->flags &= ~ISDN_NET_CALLBACK; mlp->flags &= ~ISDN_NET_CALLBACK;
break; break;
} }
lp->flags &= ~ISDN_NET_DIALMODE_MASK; /* first all bits off */ mlp->flags &= ~ISDN_NET_DIALMODE_MASK; /* first all bits off */
if (cfg->dialmode && !(cfg->dialmode & ISDN_NET_DIALMODE_MASK)) { if (cfg->dialmode && !(cfg->dialmode & ISDN_NET_DIALMODE_MASK)) {
retval = -EINVAL; retval = -EINVAL;
goto out; goto out;
} }
lp->flags |= cfg->dialmode; /* turn on selected bits */ mlp->flags |= cfg->dialmode; /* turn on selected bits */
if (lp->flags & ISDN_NET_DM_OFF) if (mlp->flags & ISDN_NET_DM_OFF)
isdn_net_hangup(idev); isdn_net_hangup(idev);
if (cfg->chargehup) if (cfg->chargehup)
lp->hupflags |= ISDN_CHARGEHUP; mlp->hupflags |= ISDN_CHARGEHUP;
else else
lp->hupflags &= ~ISDN_CHARGEHUP; mlp->hupflags &= ~ISDN_CHARGEHUP;
if (cfg->ihup) if (cfg->ihup)
lp->hupflags |= ISDN_INHUP; mlp->hupflags |= ISDN_INHUP;
else else
lp->hupflags &= ~ISDN_INHUP; mlp->hupflags &= ~ISDN_INHUP;
if (cfg->chargeint > 10) { if (cfg->chargeint > 10) {
idev->chargeint = cfg->chargeint * HZ; idev->chargeint = cfg->chargeint * HZ;
idev->charge_state = ST_CHARGE_HAVE_CINT; idev->charge_state = ST_CHARGE_HAVE_CINT;
lp->hupflags |= ISDN_MANCHARGE; mlp->hupflags |= ISDN_MANCHARGE;
} }
retval = 0; retval = 0;
...@@ -1884,48 +1813,51 @@ int ...@@ -1884,48 +1813,51 @@ int
isdn_net_getcfg(isdn_net_ioctl_cfg * cfg) isdn_net_getcfg(isdn_net_ioctl_cfg * cfg)
{ {
isdn_net_dev *idev = isdn_net_findif(cfg->name); isdn_net_dev *idev = isdn_net_findif(cfg->name);
isdn_net_local *lp = &idev->local; isdn_net_local *mlp;
if (!idev) if (!idev)
return -ENODEV; return -ENODEV;
strcpy(cfg->eaz, lp->msn); mlp = idev->mlp;
strcpy(cfg->eaz, mlp->msn);
cfg->exclusive = idev->exclusive >= 0; cfg->exclusive = idev->exclusive >= 0;
if (idev->pre_device >= 0) { if (idev->pre_device >= 0) {
sprintf(cfg->drvid, "%s,%d", dev->drvid[idev->pre_device], sprintf(cfg->drvid, "%s,%d", dev->drvid[idev->pre_device],
idev->pre_channel); idev->pre_channel);
} else } else
cfg->drvid[0] = '\0'; cfg->drvid[0] = '\0';
cfg->onhtime = lp->onhtime; cfg->onhtime = mlp->onhtime;
cfg->charge = idev->charge; cfg->charge = idev->charge;
cfg->l2_proto = lp->l2_proto; cfg->l2_proto = mlp->l2_proto;
cfg->l3_proto = lp->l3_proto; cfg->l3_proto = mlp->l3_proto;
cfg->p_encap = lp->p_encap; cfg->p_encap = mlp->p_encap;
cfg->secure = (lp->flags & ISDN_NET_SECURE) ? 1 : 0; cfg->secure = (mlp->flags & ISDN_NET_SECURE) ? 1 : 0;
cfg->callback = 0; cfg->callback = 0;
if (lp->flags & ISDN_NET_CALLBACK) if (mlp->flags & ISDN_NET_CALLBACK)
cfg->callback = 1; cfg->callback = 1;
if (lp->flags & ISDN_NET_CBOUT) if (mlp->flags & ISDN_NET_CBOUT)
cfg->callback = 2; cfg->callback = 2;
cfg->cbhup = (lp->flags & ISDN_NET_CBHUP) ? 1 : 0; cfg->cbhup = (mlp->flags & ISDN_NET_CBHUP) ? 1 : 0;
cfg->dialmode = lp->flags & ISDN_NET_DIALMODE_MASK; cfg->dialmode = mlp->flags & ISDN_NET_DIALMODE_MASK;
cfg->chargehup = (lp->hupflags & ISDN_CHARGEHUP) ? 1 : 0; cfg->chargehup = (mlp->hupflags & ISDN_CHARGEHUP) ? 1 : 0;
cfg->ihup = (lp->hupflags & ISDN_INHUP) ? 1 : 0; cfg->ihup = (mlp->hupflags & ISDN_INHUP) ? 1 : 0;
cfg->cbdelay = lp->cbdelay * 5 / HZ; cfg->cbdelay = mlp->cbdelay * 5 / HZ;
cfg->dialmax = lp->dialmax; cfg->dialmax = mlp->dialmax;
cfg->triggercps = lp->triggercps; cfg->triggercps = mlp->triggercps;
cfg->slavedelay = lp->slavedelay / HZ; cfg->slavedelay = mlp->slavedelay / HZ;
cfg->chargeint = (lp->hupflags & ISDN_CHARGEHUP) ? cfg->chargeint = (mlp->hupflags & ISDN_CHARGEHUP) ?
(idev->chargeint / HZ) : 0; (idev->chargeint / HZ) : 0;
cfg->pppbind = idev->pppbind; cfg->pppbind = idev->pppbind;
cfg->dialtimeout = lp->dialtimeout >= 0 ? lp->dialtimeout / HZ : -1; cfg->dialtimeout = mlp->dialtimeout >= 0 ? mlp->dialtimeout / HZ : -1;
cfg->dialwait = lp->dialwait / HZ; cfg->dialwait = mlp->dialwait / HZ;
if (idev->slave)
strcpy(cfg->slave, idev->slave->name); if (idev->slaves.next != &mlp->slaves)
strcpy(cfg->slave, list_entry(idev->slaves.next, isdn_net_dev, slaves)->name);
else else
cfg->slave[0] = '\0'; cfg->slave[0] = '\0';
if (idev->master) if (strcmp(mlp->dev.name, idev->name))
strcpy(cfg->master, idev->master->netdev->name); strcpy(cfg->master, mlp->dev.name);
else else
cfg->master[0] = '\0'; cfg->master[0] = '\0';
...@@ -1938,11 +1870,12 @@ isdn_net_getcfg(isdn_net_ioctl_cfg * cfg) ...@@ -1938,11 +1870,12 @@ isdn_net_getcfg(isdn_net_ioctl_cfg * cfg)
int int
isdn_net_addphone(isdn_net_ioctl_phone * phone) isdn_net_addphone(isdn_net_ioctl_phone * phone)
{ {
isdn_net_dev *p = isdn_net_findif(phone->name); isdn_net_dev *idev = isdn_net_findif(phone->name);
isdn_net_local *mlp;
unsigned long flags; unsigned long flags;
struct isdn_net_phone *n; struct isdn_net_phone *n;
if (!p) if (!idev)
return -ENODEV; return -ENODEV;
n = kmalloc(sizeof(*n), GFP_KERNEL); n = kmalloc(sizeof(*n), GFP_KERNEL);
...@@ -1950,9 +1883,10 @@ isdn_net_addphone(isdn_net_ioctl_phone * phone) ...@@ -1950,9 +1883,10 @@ isdn_net_addphone(isdn_net_ioctl_phone * phone)
return -ENOMEM; return -ENOMEM;
strcpy(n->num, phone->phone); strcpy(n->num, phone->phone);
spin_lock_irqsave(&p->local.lock, flags); mlp = idev->mlp;
list_add_tail(&n->list, &p->local.phone[phone->outgoing & 1]); spin_lock_irqsave(&mlp->lock, flags);
spin_unlock_irqrestore(&p->local.lock, flags); list_add_tail(&n->list, &mlp->phone[phone->outgoing & 1]);
spin_unlock_irqrestore(&mlp->lock, flags);
return 0; return 0;
} }
...@@ -1963,29 +1897,31 @@ isdn_net_addphone(isdn_net_ioctl_phone * phone) ...@@ -1963,29 +1897,31 @@ isdn_net_addphone(isdn_net_ioctl_phone * phone)
int int
isdn_net_getphones(isdn_net_ioctl_phone * phone, char *phones) isdn_net_getphones(isdn_net_ioctl_phone * phone, char *phones)
{ {
isdn_net_dev *p = isdn_net_findif(phone->name); isdn_net_dev *idev = isdn_net_findif(phone->name);
isdn_net_local *mlp;
unsigned long flags; unsigned long flags;
int inout = phone->outgoing & 1; int inout = phone->outgoing & 1;
int count = 0; int count = 0;
char *buf = (char *)__get_free_page(GFP_KERNEL); char *buf = (char *)__get_free_page(GFP_KERNEL);
struct isdn_net_phone *n; struct isdn_net_phone *n;
if (!p) if (!idev)
return -ENODEV; return -ENODEV;
if (!buf) if (!buf)
return -ENOMEM; return -ENOMEM;
mlp = idev->mlp;
inout &= 1; inout &= 1;
spin_lock_irqsave(&p->local.lock, flags); spin_lock_irqsave(&mlp->lock, flags);
list_for_each_entry(n, &p->local.phone[inout], list) { list_for_each_entry(n, &mlp->phone[inout], list) {
strcpy(&buf[count], n->num); strcpy(&buf[count], n->num);
count += strlen(n->num); count += strlen(n->num);
buf[count++] = ' '; buf[count++] = ' ';
if (count > PAGE_SIZE - ISDN_MSNLEN - 1) if (count > PAGE_SIZE - ISDN_MSNLEN - 1)
break; break;
} }
spin_unlock_irqrestore(&p->local.lock, flags); spin_unlock_irqrestore(&mlp->lock, flags);
if (!count) if (!count)
count++; count++;
...@@ -2030,18 +1966,20 @@ isdn_net_getpeer(isdn_net_ioctl_phone *phone, isdn_net_ioctl_phone *peer) ...@@ -2030,18 +1966,20 @@ isdn_net_getpeer(isdn_net_ioctl_phone *phone, isdn_net_ioctl_phone *peer)
int int
isdn_net_delphone(isdn_net_ioctl_phone * phone) isdn_net_delphone(isdn_net_ioctl_phone * phone)
{ {
isdn_net_dev *p = isdn_net_findif(phone->name); isdn_net_dev *idev = isdn_net_findif(phone->name);
isdn_net_local *mlp;
int inout = phone->outgoing & 1; int inout = phone->outgoing & 1;
struct isdn_net_phone *n; struct isdn_net_phone *n;
unsigned long flags; unsigned long flags;
int retval; int retval;
if (!p) if (!idev)
return -ENODEV; return -ENODEV;
mlp = idev->mlp;
retval = -EINVAL; retval = -EINVAL;
spin_lock_irqsave(&p->local.lock, flags); spin_lock_irqsave(&mlp->lock, flags);
list_for_each_entry(n, &p->local.phone[inout], list) { list_for_each_entry(n, &mlp->phone[inout], list) {
if (!strcmp(n->num, phone->phone)) { if (!strcmp(n->num, phone->phone)) {
list_del(&n->list); list_del(&n->list);
kfree(n); kfree(n);
...@@ -2049,7 +1987,7 @@ isdn_net_delphone(isdn_net_ioctl_phone * phone) ...@@ -2049,7 +1987,7 @@ isdn_net_delphone(isdn_net_ioctl_phone * phone)
break; break;
} }
} }
spin_unlock_irqrestore(&p->local.lock, flags); spin_unlock_irqrestore(&mlp->lock, flags);
return retval; return retval;
} }
...@@ -2057,21 +1995,22 @@ isdn_net_delphone(isdn_net_ioctl_phone * phone) ...@@ -2057,21 +1995,22 @@ isdn_net_delphone(isdn_net_ioctl_phone * phone)
* Delete all phone-numbers of an interface. * Delete all phone-numbers of an interface.
*/ */
static int static int
isdn_net_rmallphone(isdn_net_dev * p) isdn_net_rmallphone(isdn_net_dev *idev)
{ {
isdn_net_local *mlp = idev->mlp;
struct isdn_net_phone *n; struct isdn_net_phone *n;
unsigned long flags; unsigned long flags;
int i; int i;
spin_lock_irqsave(&p->local.lock, flags); spin_lock_irqsave(&mlp->lock, flags);
for (i = 0; i < 2; i++) { for (i = 0; i < 2; i++) {
while (!list_empty(&p->local.phone[i])) { while (!list_empty(&mlp->phone[i])) {
n = list_entry(p->local.phone[i].next, struct isdn_net_phone, list); n = list_entry(mlp->phone[i].next, struct isdn_net_phone, list);
list_del(&n->list); list_del(&n->list);
kfree(n); kfree(n);
} }
} }
spin_lock_irqsave(&p->local.lock, flags); spin_lock_irqsave(&mlp->lock, flags);
return 0; return 0;
} }
...@@ -2114,35 +2053,21 @@ isdn_net_realrm(isdn_net_dev *p) ...@@ -2114,35 +2053,21 @@ isdn_net_realrm(isdn_net_dev *p)
restore_flags(flags); restore_flags(flags);
return -EBUSY; return -EBUSY;
} }
isdn_net_set_encap(p, -1); isdn_net_set_encap(p->mlp, -1);
/* Free all phone-entries */ /* Free all phone-entries */
isdn_net_rmallphone(p); isdn_net_rmallphone(p);
/* If interface is bound exclusive, free channel-usage */ /* If interface is bound exclusive, free channel-usage */
if (p->exclusive >= 0) if (p->exclusive >= 0)
isdn_unexclusive_channel(p->pre_device, p->pre_channel); isdn_unexclusive_channel(p->pre_device, p->pre_channel);
if (p->master) {
/* It's a slave-device, so update master's slave-pointer if necessary */
if (p->master->netdev->slave == p)
p->master->netdev->slave = p->slave;
} else {
/* Unregister only if it's a master-device */
unregister_netdev(&p->local.dev);
}
/* Unlink device from chain */ /* Unlink device from chain */
list_del(&p->global_list); list_del(&p->global_list);
if (p->slave) { list_del(&p->slaves);
/* If this interface has a slave, remove it also */
char *slavename = p->slave->name; if (list_empty(&p->mlp->slaves)) {
struct list_head *l; unregister_netdev(&p->mlp->dev);
kfree(p->mlp);
list_for_each(l, &isdn_net_devs) {
isdn_net_dev *n = list_entry(l, isdn_net_dev, global_list);
if (!strcmp(n->name, slavename)) {
isdn_net_realrm(n);
break;
}
}
} }
restore_flags(flags); restore_flags(flags);
kfree(p); kfree(p);
...@@ -2156,15 +2081,15 @@ isdn_net_realrm(isdn_net_dev *p) ...@@ -2156,15 +2081,15 @@ isdn_net_realrm(isdn_net_dev *p)
int int
isdn_net_rm(char *name) isdn_net_rm(char *name)
{ {
struct list_head *l; /* FIXME: For compatibility, if a master isdn_net_dev is rm'ed,
* kill all slaves, too */
/* Search name in netdev-chain */ isdn_net_dev *idev = isdn_net_findif(name);
list_for_each(l, &isdn_net_devs) {
isdn_net_dev *p = list_entry(l, isdn_net_dev, global_list); if (!idev)
if (!strcmp(p->name, name)) return -ENODEV;
return isdn_net_realrm(p);
} return isdn_net_realrm(idev);
return -ENODEV;
} }
/* /*
...@@ -2174,24 +2099,19 @@ int ...@@ -2174,24 +2099,19 @@ int
isdn_net_rmall(void) isdn_net_rmall(void)
{ {
unsigned long flags; unsigned long flags;
int ret; int ret = 0;
/* Walk through netdev-chain */ /* Walk through netdev-chain */
save_flags(flags); save_flags(flags);
cli(); cli();
while (!list_empty(&isdn_net_devs)) { while (!list_empty(&isdn_net_devs)) {
isdn_net_dev *p = list_entry(isdn_net_devs.next, isdn_net_dev, global_list); isdn_net_dev *idev = list_entry(isdn_net_devs.next, isdn_net_dev, global_list);
ret = isdn_net_realrm(idev);
/* Remove master-devices only, slaves get removed with their master */ if (ret)
if (!p->master) { break;
if ((ret = isdn_net_realrm(p))) {
restore_flags(flags);
return ret;
}
}
} }
restore_flags(flags); restore_flags(flags);
return 0; return ret;
} }
// ISDN_NET_ENCAP_IPTYP // ISDN_NET_ENCAP_IPTYP
...@@ -2211,7 +2131,7 @@ static void ...@@ -2211,7 +2131,7 @@ static void
isdn_iptyp_receive(isdn_net_local *lp, isdn_net_dev *idev, isdn_iptyp_receive(isdn_net_local *lp, isdn_net_dev *idev,
struct sk_buff *skb) struct sk_buff *skb)
{ {
isdn_net_reset_huptimer(lp, idev); idev->huptimer = 0;
get_u16(skb->data, &skb->protocol); get_u16(skb->data, &skb->protocol);
skb_pull(skb, 2); skb_pull(skb, 2);
netif_rx(skb); netif_rx(skb);
...@@ -2242,7 +2162,7 @@ static void ...@@ -2242,7 +2162,7 @@ static void
isdn_uihdlc_receive(isdn_net_local *lp, isdn_net_dev *idev, isdn_uihdlc_receive(isdn_net_local *lp, isdn_net_dev *idev,
struct sk_buff *skb) struct sk_buff *skb)
{ {
isdn_net_reset_huptimer(lp, idev); idev->huptimer = 0;
skb_pull(skb, 2); skb_pull(skb, 2);
skb->protocol = htons(ETH_P_IP); skb->protocol = htons(ETH_P_IP);
netif_rx(skb); netif_rx(skb);
...@@ -2264,7 +2184,7 @@ static void ...@@ -2264,7 +2184,7 @@ static void
isdn_rawip_receive(isdn_net_local *lp, isdn_net_dev *idev, isdn_rawip_receive(isdn_net_local *lp, isdn_net_dev *idev,
struct sk_buff *skb) struct sk_buff *skb)
{ {
isdn_net_reset_huptimer(lp, idev); idev->huptimer = 0;
skb->protocol = htons(ETH_P_IP); skb->protocol = htons(ETH_P_IP);
netif_rx(skb); netif_rx(skb);
} }
...@@ -2337,7 +2257,7 @@ static void ...@@ -2337,7 +2257,7 @@ static void
isdn_ether_receive(isdn_net_local *lp, isdn_net_dev *idev, isdn_ether_receive(isdn_net_local *lp, isdn_net_dev *idev,
struct sk_buff *skb) struct sk_buff *skb)
{ {
isdn_net_reset_huptimer(lp, idev); idev->huptimer = 0;
skb->protocol = isdn_eth_type_trans(skb, skb->dev); skb->protocol = isdn_eth_type_trans(skb, skb->dev);
netif_rx(skb); netif_rx(skb);
} }
......
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
extern void isdn_net_init_module(void); extern void isdn_net_init_module(void);
extern int isdn_net_new(char *, struct net_device *); extern int isdn_net_new(char *, isdn_net_local *);
extern int isdn_net_newslave(char *); extern int isdn_net_newslave(char *);
extern int isdn_net_rm(char *); extern int isdn_net_rm(char *);
extern int isdn_net_rmall(void); extern int isdn_net_rmall(void);
...@@ -57,13 +57,6 @@ extern void isdn_net_writebuf_skb(isdn_net_dev *, struct sk_buff *skb); ...@@ -57,13 +57,6 @@ extern void isdn_net_writebuf_skb(isdn_net_dev *, struct sk_buff *skb);
extern void isdn_net_write_super(isdn_net_dev *, struct sk_buff *skb); extern void isdn_net_write_super(isdn_net_dev *, struct sk_buff *skb);
extern int isdn_net_online(isdn_net_dev *); extern int isdn_net_online(isdn_net_dev *);
static inline void
isdn_net_reset_huptimer(isdn_net_local *lp, isdn_net_dev *idev)
{
lp->netdev->huptimer = 0;
idev->huptimer = 0;
}
#define ISDN_NET_MAX_QUEUE_LENGTH 2 #define ISDN_NET_MAX_QUEUE_LENGTH 2
/* /*
...@@ -125,14 +118,9 @@ isdn_net_add_to_bundle(isdn_net_local *mlp, isdn_net_dev *idev) ...@@ -125,14 +118,9 @@ isdn_net_add_to_bundle(isdn_net_local *mlp, isdn_net_dev *idev)
static inline void static inline void
isdn_net_rm_from_bundle(isdn_net_dev *idev) isdn_net_rm_from_bundle(isdn_net_dev *idev)
{ {
isdn_net_local *mlp; isdn_net_local *mlp = idev->mlp;
unsigned long flags; unsigned long flags;
if (idev->master)
mlp = idev->master;
else
mlp = &idev->local;
spin_lock_irqsave(&mlp->online_lock, flags); spin_lock_irqsave(&mlp->online_lock, flags);
list_del(&idev->online); list_del(&idev->online);
spin_unlock_irqrestore(&mlp->online_lock, flags); spin_unlock_irqrestore(&mlp->online_lock, flags);
...@@ -145,10 +133,7 @@ isdn_net_rm_from_bundle(isdn_net_dev *idev) ...@@ -145,10 +133,7 @@ isdn_net_rm_from_bundle(isdn_net_dev *idev)
static inline void static inline void
isdn_net_dev_wake_queue(isdn_net_dev *idev) isdn_net_dev_wake_queue(isdn_net_dev *idev)
{ {
if (idev->master) netif_wake_queue(&idev->mlp->dev);
netif_wake_queue(&idev->master->dev);
else
netif_wake_queue(&idev->local.dev);
} }
static inline int static inline int
......
...@@ -100,9 +100,8 @@ isdn_ppp_frame_log(char *info, char *data, int len, int maxlen,int unit,int slot ...@@ -100,9 +100,8 @@ isdn_ppp_frame_log(char *info, char *data, int len, int maxlen,int unit,int slot
* 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_local * lp) isdn_ppp_free(isdn_net_dev *idev)
{ {
isdn_net_dev *idev = lp->netdev;
unsigned long flags; unsigned long flags;
struct ippp_struct *is; struct ippp_struct *is;
...@@ -116,7 +115,7 @@ isdn_ppp_free(isdn_net_local * lp) ...@@ -116,7 +115,7 @@ isdn_ppp_free(isdn_net_local * lp)
cli(); cli();
#ifdef CONFIG_ISDN_MPP #ifdef CONFIG_ISDN_MPP
spin_lock(&lp->netdev->pb->lock); spin_lock(&idev->pb->lock);
#endif #endif
isdn_net_rm_from_bundle(idev); isdn_net_rm_from_bundle(idev);
#ifdef CONFIG_ISDN_MPP #ifdef CONFIG_ISDN_MPP
...@@ -139,7 +138,7 @@ isdn_ppp_free(isdn_net_local * lp) ...@@ -139,7 +138,7 @@ isdn_ppp_free(isdn_net_local * lp)
is->state = IPPP_OPEN; /* fallback to 'OPEN but not ASSIGNED' state */ is->state = IPPP_OPEN; /* fallback to 'OPEN but not ASSIGNED' state */
if (is->debug & 0x1) if (is->debug & 0x1)
printk(KERN_DEBUG "isdn_ppp_free %d %p %p\n", idev->ppp_slot, lp, is->idev); printk(KERN_DEBUG "isdn_ppp_free %d %p\n", idev->ppp_slot, is->idev);
is->idev = NULL; /* link is down .. set lp to NULL */ is->idev = NULL; /* link is down .. set lp to NULL */
idev->ppp_slot = -1; /* is this OK ?? */ idev->ppp_slot = -1; /* is this OK ?? */
...@@ -152,9 +151,8 @@ isdn_ppp_free(isdn_net_local * lp) ...@@ -152,9 +151,8 @@ isdn_ppp_free(isdn_net_local * lp)
* bind isdn_net_local <=> ippp-device * bind isdn_net_local <=> ippp-device
*/ */
int int
isdn_ppp_bind(isdn_net_local * lp) isdn_ppp_bind(isdn_net_dev *idev)
{ {
isdn_net_dev *idev = lp->netdev;
int i; int i;
int unit = 0; int unit = 0;
long flags; long flags;
...@@ -226,10 +224,8 @@ isdn_ppp_bind(isdn_net_local * lp) ...@@ -226,10 +224,8 @@ isdn_ppp_bind(isdn_net_local * lp)
*/ */
static void static void
isdn_ppp_wakeup_daemon(isdn_net_local *lp) isdn_ppp_wakeup_daemon(isdn_net_dev *idev)
{ {
isdn_net_dev *idev = lp->netdev;
if (idev->ppp_slot < 0 || idev->ppp_slot >= ISDN_MAX_CHANNELS) { if (idev->ppp_slot < 0 || idev->ppp_slot >= ISDN_MAX_CHANNELS) {
printk(KERN_ERR "%s: ppp_slot(%d) out of range\n", printk(KERN_ERR "%s: ppp_slot(%d) out of range\n",
__FUNCTION__, idev->ppp_slot); __FUNCTION__, idev->ppp_slot);
...@@ -477,7 +473,7 @@ isdn_ppp_ioctl(struct inode *ino, struct file *file, unsigned int cmd, unsigned ...@@ -477,7 +473,7 @@ isdn_ppp_ioctl(struct inode *ino, struct file *file, unsigned int cmd, unsigned
if (val & SC_ENABLE_IP && !(is->pppcfg & SC_ENABLE_IP) && (is->state & IPPP_CONNECT)) { if (val & SC_ENABLE_IP && !(is->pppcfg & SC_ENABLE_IP) && (is->state & IPPP_CONNECT)) {
if (idev) { if (idev) {
/* OK .. we are ready to send buffers */ /* OK .. we are ready to send buffers */
netif_wake_queue(&idev->local.dev); isdn_net_dev_wake_queue(idev);
} }
} }
is->pppcfg = val; is->pppcfg = val;
...@@ -552,14 +548,16 @@ isdn_ppp_ioctl(struct inode *ino, struct file *file, unsigned int cmd, unsigned ...@@ -552,14 +548,16 @@ isdn_ppp_ioctl(struct inode *ino, struct file *file, unsigned int cmd, unsigned
return isdn_ppp_set_compressor(is, &data); return isdn_ppp_set_compressor(is, &data);
case PPPIOCGCALLINFO: case PPPIOCGCALLINFO:
{ {
isdn_net_local *mlp;
struct isdn_net_phone *phone; struct isdn_net_phone *phone;
struct pppcallinfo pci; struct pppcallinfo pci;
int i; int i;
memset((char *) &pci,0,sizeof(struct pppcallinfo)); memset((char *) &pci,0,sizeof(struct pppcallinfo));
if(idev) { if(idev) {
strncpy(pci.local_num,idev->local.msn,63); mlp = idev->mlp;
strncpy(pci.local_num, mlp->msn, 63);
i = 0; i = 0;
list_for_each_entry(phone, &idev->local.phone[1], list) { list_for_each_entry(phone, &mlp->phone[1], list) {
if (i++ == idev->dial) { if (i++ == idev->dial) {
strncpy(pci.remote_num,phone->num,63); strncpy(pci.remote_num,phone->num,63);
break; break;
...@@ -570,7 +568,7 @@ isdn_ppp_ioctl(struct inode *ino, struct file *file, unsigned int cmd, unsigned ...@@ -570,7 +568,7 @@ isdn_ppp_ioctl(struct inode *ino, struct file *file, unsigned int cmd, unsigned
pci.calltype = CALLTYPE_OUTGOING; pci.calltype = CALLTYPE_OUTGOING;
else else
pci.calltype = CALLTYPE_INCOMING; pci.calltype = CALLTYPE_INCOMING;
if(idev->local.flags & ISDN_NET_CALLBACK) if(mlp->flags & ISDN_NET_CALLBACK)
pci.calltype |= CALLTYPE_CALLBACK; pci.calltype |= CALLTYPE_CALLBACK;
} }
return set_arg((void *)arg,&pci,sizeof(struct pppcallinfo)); return set_arg((void *)arg,&pci,sizeof(struct pppcallinfo));
...@@ -779,7 +777,7 @@ isdn_ppp_write(struct file *file, const char *buf, size_t count, loff_t *off) ...@@ -779,7 +777,7 @@ isdn_ppp_write(struct file *file, const char *buf, size_t count, loff_t *off)
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,idev->ppp_slot);
} }
isdn_ppp_send_ccp(idev,&idev->local,skb); /* keeps CCP/compression states in sync */ isdn_ppp_send_ccp(idev,idev->mlp,skb); /* keeps CCP/compression states in sync */
isdn_net_write_super(idev, skb); isdn_net_write_super(idev, skb);
} }
...@@ -914,7 +912,7 @@ static void isdn_ppp_receive(isdn_net_local *lp, isdn_net_dev *idev, ...@@ -914,7 +912,7 @@ static void isdn_ppp_receive(isdn_net_local *lp, isdn_net_dev *idev,
* huptimer on LCP packets. * huptimer on LCP packets.
*/ */
if (PPP_PROTOCOL(skb->data) != PPP_LCP) if (PPP_PROTOCOL(skb->data) != PPP_LCP)
isdn_net_reset_huptimer(lp, idev); idev->huptimer = 0;
slot = idev->ppp_slot; slot = idev->ppp_slot;
if (slot < 0 || slot > ISDN_MAX_CHANNELS) { if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
...@@ -979,14 +977,6 @@ isdn_ppp_push_higher(isdn_net_local *lp, isdn_net_dev *idev, ...@@ -979,14 +977,6 @@ isdn_ppp_push_higher(isdn_net_local *lp, isdn_net_dev *idev,
} }
is = ippp_table[slot]; is = ippp_table[slot];
if (idev->master) { // FIXME?
slot = idev->master->netdev->ppp_slot;
if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
printk(KERN_ERR "isdn_ppp_push_higher: master->ppp_slot(%d)\n",
slot);
goto drop_packet;
}
}
mis = ippp_table[slot]; mis = ippp_table[slot];
if (is->debug & 0x10) { if (is->debug & 0x10) {
...@@ -1017,12 +1007,12 @@ isdn_ppp_push_higher(isdn_net_local *lp, isdn_net_dev *idev, ...@@ -1017,12 +1007,12 @@ isdn_ppp_push_higher(isdn_net_local *lp, isdn_net_dev *idev,
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 (lp->netdev->ppp_slot < 0) { if (idev->ppp_slot < 0) {
printk(KERN_ERR "%s: net_dev->ppp_slot(%d) out of range\n", printk(KERN_ERR "%s: net_dev->ppp_slot(%d) out of range\n",
__FUNCTION__ , lp->netdev->ppp_slot); __FUNCTION__ , idev->ppp_slot);
goto drop_packet; goto drop_packet;
} }
if (slhc_remember(ippp_table[lp->netdev->ppp_slot]->slcomp, skb->data, skb->len) <= 0) { if (slhc_remember(ippp_table[idev->ppp_slot]->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_packet; goto drop_packet;
} }
...@@ -1043,12 +1033,12 @@ isdn_ppp_push_higher(isdn_net_local *lp, isdn_net_dev *idev, ...@@ -1043,12 +1033,12 @@ isdn_ppp_push_higher(isdn_net_local *lp, isdn_net_dev *idev,
} }
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);
if (lp->netdev->ppp_slot < 0) { if (idev->ppp_slot < 0) {
printk(KERN_ERR "%s: net_dev->ppp_slot(%d) out of range\n", printk(KERN_ERR "%s: net_dev->ppp_slot(%d) out of range\n",
__FUNCTION__ , lp->netdev->ppp_slot); __FUNCTION__ , idev->ppp_slot);
goto drop_packet; goto drop_packet;
} }
pkt_len = slhc_uncompress(ippp_table[lp->netdev->ppp_slot]->slcomp, pkt_len = slhc_uncompress(ippp_table[idev->ppp_slot]->slcomp,
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)
...@@ -1061,7 +1051,7 @@ isdn_ppp_push_higher(isdn_net_local *lp, isdn_net_dev *idev, ...@@ -1061,7 +1051,7 @@ isdn_ppp_push_higher(isdn_net_local *lp, isdn_net_dev *idev,
#endif #endif
case PPP_CCP: case PPP_CCP:
case PPP_CCPFRAG: case PPP_CCPFRAG:
isdn_ppp_receive_ccp(lp->netdev,lp,skb,proto); isdn_ppp_receive_ccp(idev,lp,skb,proto);
/* Dont pop up ResetReq/Ack stuff to the daemon any /* Dont pop up ResetReq/Ack stuff to the daemon any
longer - the job is done already */ longer - the job is done already */
if(skb->data[0] == CCP_RESETREQ || if(skb->data[0] == CCP_RESETREQ ||
...@@ -1125,17 +1115,15 @@ static unsigned char *isdn_ppp_skb_push(struct sk_buff **skb_p,int len) ...@@ -1125,17 +1115,15 @@ static unsigned char *isdn_ppp_skb_push(struct sk_buff **skb_p,int len)
int int
isdn_ppp_xmit(struct sk_buff *skb, struct net_device *netdev) isdn_ppp_xmit(struct sk_buff *skb, struct net_device *netdev)
{ {
isdn_net_local *mlp; isdn_net_local *mlp = netdev->priv;
isdn_net_dev *idev; isdn_net_dev *idev = list_entry(mlp->online.next, isdn_net_dev, online);
isdn_net_dev *nd;
unsigned int proto = PPP_IP; /* 0x21 */ unsigned int proto = PPP_IP; /* 0x21 */
struct ippp_struct *ipt,*ipts; struct ippp_struct *ipt,*ipts;
int slot; int slot;
mlp = netdev->priv; mlp = netdev->priv;
nd = mlp->netdev; /* get master lp */
slot = nd->ppp_slot; slot = idev->ppp_slot;
if (slot < 0 || slot > ISDN_MAX_CHANNELS) { if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
printk(KERN_ERR "isdn_ppp_xmit: lp->ppp_slot(%d)\n", printk(KERN_ERR "isdn_ppp_xmit: lp->ppp_slot(%d)\n",
slot); slot);
...@@ -1779,7 +1767,7 @@ isdn_ppp_bundle(struct ippp_struct *is, int unit) ...@@ -1779,7 +1767,7 @@ isdn_ppp_bundle(struct ippp_struct *is, int unit)
spin_lock_irqsave(&p->pb->lock, flags); spin_lock_irqsave(&p->pb->lock, flags);
nidev = is->idev; nidev = is->idev;
idev = list_entry(p->local.online.next, isdn_net_dev, online); idev = list_entry(p->mlp->online.next, isdn_net_dev, online);
if( nidev->ppp_slot < 0 || nidev->ppp_slot >= ISDN_MAX_CHANNELS || if( nidev->ppp_slot < 0 || nidev->ppp_slot >= ISDN_MAX_CHANNELS ||
idev ->ppp_slot < 0 || idev ->ppp_slot >= ISDN_MAX_CHANNELS ) { idev ->ppp_slot < 0 || idev ->ppp_slot >= ISDN_MAX_CHANNELS ) {
printk(KERN_ERR "ippp_bundle: binding to invalid slot %d\n", printk(KERN_ERR "ippp_bundle: binding to invalid slot %d\n",
...@@ -1789,7 +1777,7 @@ isdn_ppp_bundle(struct ippp_struct *is, int unit) ...@@ -1789,7 +1777,7 @@ isdn_ppp_bundle(struct ippp_struct *is, int unit)
goto out; goto out;
} }
isdn_net_add_to_bundle(&p->local, nidev); isdn_net_add_to_bundle(p->mlp, nidev);
ippp_table[nidev->ppp_slot]->unit = ippp_table[idev->ppp_slot]->unit; ippp_table[nidev->ppp_slot]->unit = ippp_table[idev->ppp_slot]->unit;
...@@ -1798,7 +1786,7 @@ isdn_ppp_bundle(struct ippp_struct *is, int unit) ...@@ -1798,7 +1786,7 @@ isdn_ppp_bundle(struct ippp_struct *is, int unit)
(SC_ENABLE_IP | SC_NO_TCP_CCID | SC_REJ_COMP_TCP); (SC_ENABLE_IP | SC_NO_TCP_CCID | SC_REJ_COMP_TCP);
ippp_table[nidev->ppp_slot]->mpppcfg |= ippp_table[idev->ppp_slot]->mpppcfg & ippp_table[nidev->ppp_slot]->mpppcfg |= ippp_table[idev->ppp_slot]->mpppcfg &
(SC_MP_PROT | SC_REJ_MP_PROT | SC_OUT_SHORT_SEQ | SC_IN_SHORT_SEQ); (SC_MP_PROT | SC_REJ_MP_PROT | SC_OUT_SHORT_SEQ | SC_IN_SHORT_SEQ);
rc = isdn_ppp_mp_init(&nidev->local, p->pb); rc = isdn_ppp_mp_init(nidev->mlp, p->pb);
out: out:
spin_unlock_irqrestore(&p->pb->lock, flags); spin_unlock_irqrestore(&p->pb->lock, flags);
return rc; return rc;
...@@ -1871,7 +1859,7 @@ isdn_ppp_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) ...@@ -1871,7 +1859,7 @@ isdn_ppp_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
if(copy_to_user(r, PPP_VERSION, len)) error = -EFAULT; if(copy_to_user(r, PPP_VERSION, len)) error = -EFAULT;
break; break;
case SIOCGPPPSTATS: case SIOCGPPPSTATS:
error = isdn_ppp_dev_ioctl_stats(lp->netdev->ppp_slot, ifr, dev); error = isdn_ppp_dev_ioctl_stats(0, ifr, dev);
break; break;
default: default:
error = -EINVAL; error = -EINVAL;
...@@ -1912,14 +1900,12 @@ isdn_ppp_dial_slave(char *name) ...@@ -1912,14 +1900,12 @@ isdn_ppp_dial_slave(char *name)
{ {
#ifdef CONFIG_ISDN_MPP #ifdef CONFIG_ISDN_MPP
isdn_net_dev *idev; isdn_net_dev *idev;
isdn_net_local *lp;
isdn_net_dev *sdev; isdn_net_dev *sdev;
idev = isdn_net_findif(name); idev = isdn_net_findif(name);
if (!idev) if (!idev)
return 1; return 1;
lp = &idev->local;
if (!isdn_net_bound(idev)) if (!isdn_net_bound(idev))
return 5; return 5;
...@@ -2456,10 +2442,9 @@ static struct sk_buff *isdn_ppp_compress(struct sk_buff *skb_in,int *proto, ...@@ -2456,10 +2442,9 @@ static struct sk_buff *isdn_ppp_compress(struct sk_buff *skb_in,int *proto,
* we received a CCP frame .. * we received a CCP frame ..
* not a clean solution, but we MUST handle a few cases in the kernel * not a clean solution, but we MUST handle a few cases in the kernel
*/ */
static void isdn_ppp_receive_ccp(isdn_net_dev *net_dev, isdn_net_local *lp, static void isdn_ppp_receive_ccp(isdn_net_dev *idev, isdn_net_local *lp,
struct sk_buff *skb,int proto) struct sk_buff *skb,int proto)
{ {
isdn_net_dev *idev = lp->netdev;
struct ippp_struct *is; struct ippp_struct *is;
struct ippp_struct *mis; struct ippp_struct *mis;
int len; int len;
...@@ -2476,16 +2461,7 @@ static void isdn_ppp_receive_ccp(isdn_net_dev *net_dev, isdn_net_local *lp, ...@@ -2476,16 +2461,7 @@ static void isdn_ppp_receive_ccp(isdn_net_dev *net_dev, isdn_net_local *lp,
is = ippp_table[idev->ppp_slot]; is = ippp_table[idev->ppp_slot];
isdn_ppp_frame_log("ccp-rcv", skb->data, skb->len, 32, is->unit,idev->ppp_slot); isdn_ppp_frame_log("ccp-rcv", skb->data, skb->len, 32, is->unit,idev->ppp_slot);
if (idev->master) { mis = is;
int slot = idev->master->netdev->ppp_slot;
if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
printk(KERN_ERR "%s: slot(%d) out of range\n",
__FUNCTION__ , slot);
return;
}
mis = ippp_table[slot];
} else
mis = is;
switch(skb->data[0]) { switch(skb->data[0]) {
case CCP_CONFREQ: case CCP_CONFREQ:
...@@ -2634,9 +2610,8 @@ static void isdn_ppp_receive_ccp(isdn_net_dev *net_dev, isdn_net_local *lp, ...@@ -2634,9 +2610,8 @@ static void isdn_ppp_receive_ccp(isdn_net_dev *net_dev, isdn_net_local *lp,
* and I tried to modify this file according to that. --abp * and I tried to modify this file according to that. --abp
*/ */
static void isdn_ppp_send_ccp(isdn_net_dev *net_dev, isdn_net_local *lp, struct sk_buff *skb) static void isdn_ppp_send_ccp(isdn_net_dev *idev, isdn_net_local *lp, struct sk_buff *skb)
{ {
isdn_net_dev *idev = lp->netdev;
struct ippp_struct *mis,*is; struct ippp_struct *mis,*is;
int proto, slot = idev->ppp_slot; int proto, slot = idev->ppp_slot;
unsigned char *data; unsigned char *data;
...@@ -2664,16 +2639,7 @@ static void isdn_ppp_send_ccp(isdn_net_dev *net_dev, isdn_net_local *lp, struct ...@@ -2664,16 +2639,7 @@ static void isdn_ppp_send_ccp(isdn_net_dev *net_dev, isdn_net_local *lp, struct
printk(KERN_DEBUG "Received CCP frame from daemon:\n"); printk(KERN_DEBUG "Received CCP frame from daemon:\n");
isdn_ppp_frame_log("ccp-xmit", skb->data, skb->len, 32, is->unit,idev->ppp_slot); isdn_ppp_frame_log("ccp-xmit", skb->data, skb->len, 32, is->unit,idev->ppp_slot);
if (idev->master) { mis = is;
slot = idev->master->netdev->ppp_slot;
if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
printk(KERN_ERR "%s: slot(%d) out of range\n",
__FUNCTION__ , slot);
return;
}
mis = ippp_table[slot];
} else
mis = is;
if (mis != is) if (mis != is)
printk(KERN_DEBUG "isdn_ppp: Ouch! Master CCP sends on slave slot!\n"); printk(KERN_DEBUG "isdn_ppp: Ouch! Master CCP sends on slave slot!\n");
......
...@@ -294,17 +294,17 @@ struct isdn_netif_ops { ...@@ -294,17 +294,17 @@ struct isdn_netif_ops {
unsigned short flags; /* interface flags (a la BSD) */ unsigned short flags; /* interface flags (a la BSD) */
unsigned short type; /* interface hardware type */ unsigned short type; /* interface hardware type */
unsigned char addr_len;/* hardware address length */ unsigned char addr_len;/* hardware address length */
void (*receive)(struct isdn_net_local_s *lp, void (*receive)(struct isdn_net_local_s *,
struct isdn_net_dev_s *idev, struct isdn_net_dev_s *,
struct sk_buff *skb); struct sk_buff *);
void (*connected)(struct isdn_net_local_s *lp); void (*connected)(struct isdn_net_dev_s *);
void (*disconnected)(struct isdn_net_local_s *lp); void (*disconnected)(struct isdn_net_dev_s *);
int (*bind)(struct isdn_net_local_s *lp); int (*bind)(struct isdn_net_dev_s *);
void (*unbind)(struct isdn_net_local_s *lp); void (*unbind)(struct isdn_net_dev_s *);
int (*init)(struct isdn_net_local_s *lp); int (*init)(struct isdn_net_local_s *);
void (*cleanup)(struct isdn_net_local_s *lp); void (*cleanup)(struct isdn_net_local_s *);
int (*open)(struct isdn_net_local_s *lp); int (*open)(struct isdn_net_local_s *);
void (*close)(struct isdn_net_local_s *lp); void (*close)(struct isdn_net_local_s *);
}; };
/* Local interface-data */ /* Local interface-data */
...@@ -313,7 +313,6 @@ typedef struct isdn_net_local_s { ...@@ -313,7 +313,6 @@ typedef struct isdn_net_local_s {
spinlock_t lock; spinlock_t lock;
struct net_device_stats stats; /* Ethernet Statistics */ struct net_device_stats stats; /* Ethernet Statistics */
int flags; /* Connection-flags */ int flags; /* Connection-flags */
int dialretry; /* Counter for Dialout-retries */
int dialmax; /* Max. Number of Dial-retries */ int dialmax; /* Max. Number of Dial-retries */
int dialtimeout; /* How long shall we try on dialing */ int dialtimeout; /* How long shall we try on dialing */
int dialwait; /* wait after failed attempt */ int dialwait; /* wait after failed attempt */
...@@ -334,8 +333,8 @@ typedef struct isdn_net_local_s { ...@@ -334,8 +333,8 @@ typedef struct isdn_net_local_s {
struct list_head phone[2]; /* List of remote-phonenumbers */ struct list_head phone[2]; /* List of remote-phonenumbers */
/* phone[0] = Incoming Numbers */ /* phone[0] = Incoming Numbers */
/* phone[1] = Outgoing Numbers */ /* phone[1] = Outgoing Numbers */
struct isdn_net_dev_s *netdev; /* Ptr to netdev */
struct list_head slaves; /* list of all bundled channels */
struct list_head online; /* circular list of all bundled struct list_head online; /* circular list of all bundled
channels, which are currently channels, which are currently
online */ online */
...@@ -361,8 +360,6 @@ typedef struct isdn_net_local_s { ...@@ -361,8 +360,6 @@ typedef struct isdn_net_local_s {
/* the interface itself */ /* the interface itself */
typedef struct isdn_net_dev_s { typedef struct isdn_net_dev_s {
isdn_net_local local;
int isdn_slot; /* Index to isdn device/channel */ int isdn_slot; /* Index to isdn device/channel */
int pre_device; /* Preselected isdn-device */ int pre_device; /* Preselected isdn-device */
int pre_channel; /* Preselected isdn-channel */ int pre_channel; /* Preselected isdn-channel */
...@@ -375,6 +372,7 @@ typedef struct isdn_net_dev_s { ...@@ -375,6 +372,7 @@ typedef struct isdn_net_dev_s {
int outgoing; /* Flag: outgoing call */ int outgoing; /* Flag: outgoing call */
unsigned long dialstarted; /* first dialing-attempt */ unsigned long dialstarted; /* first dialing-attempt */
unsigned long dialwait_timer;/* earliest next dialing-attempt */ unsigned long dialwait_timer;/* earliest next dialing-attempt */
int dialretry; /* Counter for Dialout-retries */
int cps; /* current speed of this interface */ int cps; /* current speed of this interface */
int transcount; /* byte-counter for cps-calculation */ int transcount; /* byte-counter for cps-calculation */
...@@ -401,9 +399,10 @@ typedef struct isdn_net_dev_s { ...@@ -401,9 +399,10 @@ typedef struct isdn_net_dev_s {
/* queued in HL driver */ /* queued in HL driver */
struct tasklet_struct tlet; struct tasklet_struct tlet;
isdn_net_local *master; /* Ptr to Master device for slaves */ isdn_net_local *mlp; /* Ptr to master device for all devs*/
struct isdn_net_dev_s *slave; /* Ptr to Slave device for masters */ struct isdn_net_dev_s *slave; /* Ptr to Slave device for masters */
struct list_head slaves; /* Members of local->slaves */
struct list_head online; /* Members of local->online */ struct list_head online; /* Members of local->online */
char name[10]; /* Name of device */ char name[10]; /* Name of device */
......
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