Commit 0066476b authored by Kai Germaschewski's avatar Kai Germaschewski

ISDN: More sorting out of members for isdn_net_local / isdn_net_dev

There is a one-to-one relation between struct net_device and
isdn_net_local, so reflect that in the declaration. There is
one list of active channels per network interface, so put
the list head into isdn_net_local, the list members are isdn_net_dev's.
parent 2f1efd68
......@@ -240,7 +240,7 @@ isdn_net_ciscohdlck_slarp_send_reply(isdn_net_local *lp)
u32 addr = 0; /* local ipv4 address */
u32 mask = 0; /* local netmask */
if ((in_dev = lp->netdev->dev.ip_ptr) != NULL) {
if ((in_dev = lp->dev.ip_ptr) != NULL) {
/* take primary(first) address of interface */
struct in_ifaddr *ifa = in_dev->ifa_list;
if (ifa != NULL) {
......@@ -337,10 +337,9 @@ isdn_net_ciscohdlck_slarp_in(isdn_net_local *lp, struct sk_buff *skb)
}
static void
isdn_ciscohdlck_receive(isdn_net_dev *idev, isdn_net_local *olp,
isdn_ciscohdlck_receive(isdn_net_local *lp, isdn_net_dev *idev,
struct sk_buff *skb)
{
isdn_net_local *lp = &idev->local;
unsigned char *p;
u8 addr;
u8 ctrl;
......@@ -373,7 +372,7 @@ isdn_ciscohdlck_receive(isdn_net_dev *idev, isdn_net_local *olp,
goto out_free;
default:
/* no special cisco protocol */
isdn_net_reset_huptimer(idev, olp->netdev);
isdn_net_reset_huptimer(lp, idev);
skb->protocol = htons(type);
netif_rx(skb);
return;
......
......@@ -93,15 +93,15 @@ LIST_HEAD(isdn_net_devs); /* Linked list of isdn_net_dev's */
* For slaves, look at the corresponding master.
*/
static inline int
isdn_net_device_started(isdn_net_dev *n)
isdn_net_device_started(isdn_net_dev *idev)
{
isdn_net_local *lp = &n->local;
struct net_device *dev;
if (lp->master)
dev = lp->master;
if (idev->master)
dev = &idev->master->dev;
else
dev = &n->dev;
dev = &idev->local.dev;
return netif_running(dev);
}
......@@ -112,12 +112,10 @@ isdn_net_device_started(isdn_net_dev *n)
static inline void
isdn_net_dev_stop_queue(isdn_net_dev *idev)
{
isdn_net_local *lp = &idev->local;
if (lp->master)
netif_stop_queue(lp->master);
if (idev->master)
netif_stop_queue(&idev->master->dev);
else
netif_stop_queue(&lp->netdev->dev);
netif_stop_queue(&idev->local.dev);
}
/*
......@@ -128,30 +126,28 @@ isdn_net_dev_stop_queue(isdn_net_dev *idev)
static inline int
isdn_net_device_busy(isdn_net_dev *idev)
{
isdn_net_local *lp, *nlp;
isdn_net_dev *nd;
isdn_net_dev *ndev;
isdn_net_local *mlp;
unsigned long flags;
if (!isdn_net_dev_busy(idev))
return 0;
lp = &idev->local;
if (lp->master)
nd = ((isdn_net_local *) lp->master->priv)->netdev;
if (idev->master)
mlp = idev->master;
else
nd = lp->netdev;
mlp = &idev->local;
spin_lock_irqsave(&nd->queue_lock, flags);
nlp = lp->next;
while (nlp != lp) {
if (!isdn_net_dev_busy(nlp->netdev)) {
spin_unlock_irqrestore(&nd->queue_lock, flags);
spin_lock_irqsave(&mlp->queue_lock, flags);
ndev = idev->next;
while (ndev != idev) {
if (!isdn_net_dev_busy(ndev)) {
spin_unlock_irqrestore(&mlp->queue_lock, flags);
return 0;
}
nlp = nlp->next;
ndev = ndev->next;
}
spin_unlock_irqrestore(&nd->queue_lock, flags);
spin_unlock_irqrestore(&mlp->queue_lock, flags);
return 1;
}
......@@ -281,12 +277,12 @@ isdn_net_unbind_channel(isdn_net_local * lp)
skb_queue_purge(&idev->super_tx_queue);
if (!lp->master) { /* reset only master device */
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->netdev->dev.qdisc);
qdisc_reset(lp->dev.qdisc);
}
idev->dialstate = ST_NULL;
if (idev->isdn_slot >= 0) {
......@@ -386,23 +382,23 @@ static void isdn_net_hup_timer(unsigned long data)
mod_timer(&idev->hup_timer, idev->hup_timer.expires + HZ);
}
static void isdn_net_lp_disconnected(isdn_net_local *lp)
static void isdn_net_lp_disconnected(isdn_net_dev *idev)
{
isdn_net_rm_from_bundle(lp);
isdn_net_rm_from_bundle(idev);
}
static void isdn_net_connected(isdn_net_local *lp)
static void isdn_net_connected(isdn_net_dev *idev)
{
isdn_net_dev *idev = lp->netdev;
isdn_net_local *lp = &idev->local;
idev->dialstate = ST_ACTIVE;
idev->hup_timer.expires = jiffies + HZ;
add_timer(&idev->hup_timer);
if (lp->p_encap != ISDN_NET_ENCAP_SYNCPPP) {
if (lp->master) { /* is lp a slave? */
isdn_net_dev *nd = ((isdn_net_local *)lp->master->priv)->netdev;
isdn_net_add_to_bundle(nd, lp);
if (idev->master) { /* is lp a slave? */
isdn_net_local *mlp = idev->master;
isdn_net_add_to_bundle(mlp, idev);
}
}
printk(KERN_INFO "isdn_net: %s connected\n", idev->name);
......@@ -580,7 +576,7 @@ isdn_net_handle_event(isdn_net_local *lp, int pr, void *arg)
if (lp->ops->disconnected)
lp->ops->disconnected(lp);
isdn_net_lp_disconnected(lp);
isdn_net_lp_disconnected(idev);
isdn_slot_all_eaz(idev->isdn_slot);
printk(KERN_INFO "%s: remote hangup\n", idev->name);
printk(KERN_INFO "%s: Chargesum is %d\n", idev->name,
......@@ -647,7 +643,7 @@ isdn_net_handle_event(isdn_net_local *lp, int pr, void *arg)
case ISDN_STAT_BCONN:
del_timer(&idev->dial_timer);
isdn_slot_set_usage(idev->isdn_slot, isdn_slot_usage(idev->isdn_slot) | ISDN_USAGE_OUTGOING);
isdn_net_connected(lp);
isdn_net_connected(idev);
return 1;
case ISDN_STAT_DHUP:
del_timer(&idev->dial_timer);
......@@ -686,7 +682,7 @@ isdn_net_handle_event(isdn_net_local *lp, int pr, void *arg)
case ISDN_STAT_BCONN:
del_timer(&idev->dial_timer);
isdn_slot_set_rx_netdev(idev->isdn_slot, idev);
isdn_net_connected(lp);
isdn_net_connected(idev);
return 1;
case ISDN_STAT_DHUP:
del_timer(&idev->dial_timer);
......@@ -726,21 +722,20 @@ isdn_net_hangup(isdn_net_dev *idev)
return;
// FIXME ugly and recursive
if (lp->slave != NULL) {
isdn_net_local *slp = (isdn_net_local *)lp->slave->priv;
isdn_net_dev *sidev = slp->netdev;
if (isdn_net_bound(sidev)) {
if (idev->slave) {
isdn_net_dev *sdev = idev->slave;
if (isdn_net_bound(sdev)) {
printk(KERN_INFO
"isdn_net: hang up slave %s before %s\n",
sidev->name, idev->name);
isdn_net_hangup(sidev);
sdev->name, idev->name);
isdn_net_hangup(sdev);
}
}
printk(KERN_INFO "isdn_net: local hangup %s\n", idev->name);
if (lp->ops->disconnected)
lp->ops->disconnected(lp);
isdn_net_lp_disconnected(lp);
isdn_net_lp_disconnected(idev);
isdn_slot_command(idev->isdn_slot, ISDN_CMD_HANGUP, &cmd);
printk(KERN_INFO "%s: Chargesum is %d\n", idev->name, idev->charge);
......@@ -947,23 +942,18 @@ void isdn_net_writebuf_skb(isdn_net_dev *idev, struct sk_buff *skb)
static int
isdn_net_xmit(struct net_device *ndev, struct sk_buff *skb)
{
isdn_net_dev *nd, *idev;
isdn_net_local *slp;
isdn_net_local *mlp;
isdn_net_dev *sdev;
isdn_net_local *lp = ndev->priv;
isdn_net_dev *idev = lp->netdev;
int retv = 0;
if (lp->master) {
isdn_BUG();
dev_kfree_skb(skb);
return 0;
}
/* For the other encaps the header has already been built */
if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) {
return isdn_ppp_xmit(skb, ndev);
}
nd = ((isdn_net_local *) ndev->priv)->netdev;
idev = isdn_net_get_locked_dev(nd);
mlp = ndev->priv;
idev = isdn_net_get_locked_dev(mlp);
if (!idev) {
printk(KERN_WARNING "%s: all channels busy - requeuing!\n", ndev->name);
return 1;
......@@ -990,7 +980,7 @@ isdn_net_xmit(struct net_device *ndev, struct sk_buff *skb)
printk(KERN_DEBUG "%s: %d bogocps\n", idev->name, idev->cps);
if (idev->cps > lp->triggercps) {
if (lp->slave) {
if (idev->slave) {
if (!idev->sqfull) {
/* First time overload: set timestamp only */
idev->sqfull = 1;
......@@ -998,9 +988,9 @@ isdn_net_xmit(struct net_device *ndev, struct sk_buff *skb)
} else {
/* subsequent overload: if slavedelay exceeded, start dialing */
if (time_after(jiffies, idev->sqfull_stamp + lp->slavedelay)) {
slp = lp->slave->priv;
if (!isdn_net_bound(slp->netdev)) {
isdn_net_force_dial_idev(((isdn_net_local *) lp->slave->priv)->netdev);
sdev = idev->slave;
if (!isdn_net_bound(sdev)) {
isdn_net_force_dial_idev(sdev);
}
}
}
......@@ -1010,7 +1000,7 @@ isdn_net_xmit(struct net_device *ndev, struct sk_buff *skb)
idev->sqfull = 0;
}
/* this is a hack to allow auto-hangup for slaves on moderate loads */
nd->queue = &nd->local;
mlp->queue = mlp->netdev;
}
return retv;
......@@ -1124,18 +1114,19 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
static int
isdn_net_close(struct net_device *dev)
{
struct net_device *p;
isdn_net_local *lp = dev->priv;
isdn_net_dev *idev = lp->netdev;
isdn_net_dev *sdev;
if (lp->ops->close)
lp->ops->close(lp);
netif_stop_queue(dev);
for (p = lp->slave; p; p = ((isdn_net_local *) p->priv)->slave)
isdn_net_hangup(p->priv);
for (sdev = idev->slave; sdev; sdev = sdev->slave)
isdn_net_hangup(sdev);
isdn_net_hangup(dev->priv);
isdn_net_hangup(idev);
isdn_MOD_DEC_USE_COUNT();
return 0;
}
......@@ -1154,31 +1145,29 @@ isdn_net_get_stats(struct net_device *dev)
* Got a packet from ISDN-Channel.
*/
static void
isdn_net_receive(struct net_device *ndev, struct sk_buff *skb)
isdn_net_receive(isdn_net_dev *idev, struct sk_buff *skb)
{
isdn_net_local *lp = (isdn_net_local *) ndev->priv;
isdn_net_dev *idev = lp->netdev;
isdn_net_local *olp = lp; /* original 'lp' */
isdn_net_local *lp;
struct net_device *ndev;
idev->transcount += skb->len;
lp->stats.rx_packets++;
lp->stats.rx_bytes += skb->len;
if (lp->master) {
if (idev->master) {
/* Bundling: If device is a slave-device, deliver to master, also
* handle master's statistics and hangup-timeout
*/
ndev = lp->master;
lp = (isdn_net_local *) ndev->priv;
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->mac.raw = skb->data;
isdn_dumppkt("R:", skb->data, skb->len, 40);
lp->ops->receive(lp->netdev, olp, skb);
lp->ops->receive(lp, idev, skb);
}
/*
......@@ -1197,7 +1186,7 @@ isdn_net_rcv_skb(int idx, struct sk_buff *skb)
if (!isdn_net_online(idev))
return 0;
isdn_net_receive(&idev->dev, skb);
isdn_net_receive(idev, skb);
return 0;
}
......@@ -1405,23 +1394,23 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup)
/* Interface is up, now see if it's a slave. If so, see if
* it's master and parent slave is online. If not, reject the call.
*/
if (lp->master) {
isdn_net_local *mlp = (isdn_net_local *) lp->master->priv;
if (idev->master) {
isdn_net_dev *pdev = idev->master->netdev;
printk(KERN_DEBUG "ICALLslv: %s\n", idev->name);
printk(KERN_DEBUG "master=%s\n", mlp->netdev->name);
if (isdn_net_bound(mlp->netdev)) {
printk(KERN_DEBUG "master=%s\n", pdev->name);
if (isdn_net_bound(pdev)) {
printk(KERN_DEBUG "master online\n");
/* Master is online, find parent-slave (master if first slave) */
while (mlp->slave) {
if ((isdn_net_local *) mlp->slave->priv == lp)
while (pdev->slave) {
if (pdev->slave == idev)
break;
mlp = (isdn_net_local *) mlp->slave->priv;
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(mlp->netdev));
if (!isdn_net_bound(mlp->netdev)) {
printk(KERN_DEBUG "mlpf: %d\n", isdn_net_bound(pdev));
if (!isdn_net_bound(pdev)) {
continue;
}
}
......@@ -1557,6 +1546,7 @@ int
isdn_net_new(char *name, struct net_device *master)
{
int retval;
isdn_net_local *mlp = master->priv;
isdn_net_dev *netdev;
/* Avoid creating an existing interface */
......@@ -1570,29 +1560,25 @@ isdn_net_new(char *name, struct net_device *master)
}
memset(netdev, 0, sizeof(isdn_net_dev));
strcpy(netdev->name, name);
strcpy(netdev->dev.name, name);
netdev->dev.priv = &netdev->local;
netdev->dev.init = isdn_net_init;
strcpy(netdev->local.dev.name, name);
netdev->local.dev.priv = &netdev->local;
netdev->local.dev.init = isdn_net_init;
if (master) {
/* Device shall be a slave */
struct net_device *p = (((isdn_net_local *) master->priv)->slave);
struct net_device *q = master;
isdn_net_dev *p = mlp->netdev;
netdev->local.master = master;
/* Put device at end of slave-chain */
while (p) {
q = p;
p = (((isdn_net_local *) p->priv)->slave);
}
((isdn_net_local *) q->priv)->slave = &(netdev->dev);
while (p->slave)
p = p->slave;
p->slave = netdev;
} else {
/* Device shall be a master */
/*
* Watchdog timer (currently) for master only.
*/
netdev->dev.tx_timeout = isdn_net_tx_timeout;
netdev->dev.watchdog_timeo = ISDN_NET_TX_TIMEOUT;
retval = register_netdev(&netdev->dev);
netdev->local.dev.tx_timeout = isdn_net_tx_timeout;
netdev->local.dev.watchdog_timeo = ISDN_NET_TX_TIMEOUT;
retval = register_netdev(&netdev->local.dev);
if (retval) {
printk(KERN_WARNING "isdn_net: Could not register net-device\n");
kfree(netdev);
......@@ -1601,12 +1587,12 @@ isdn_net_new(char *name, struct net_device *master)
}
netdev->local.magic = ISDN_NET_MAGIC;
netdev->queue = &netdev->local;
spin_lock_init(&netdev->queue_lock);
netdev->local.queue = netdev;
spin_lock_init(&netdev->local.queue_lock);
netdev->local.last = &netdev->local;
netdev->last = netdev;
netdev->next = netdev;
netdev->local.netdev = netdev;
netdev->local.next = &netdev->local;
netdev->tqueue.sync = 0;
netdev->tqueue.routine = isdn_net_softint;
......@@ -1669,19 +1655,19 @@ isdn_net_newslave(char *parm)
if (!(m = isdn_net_findif(parm)))
return -ESRCH;
/* Master must be a real interface, not a slave */
if (m->local.master)
if (m->master)
return -ENXIO;
/* Master must not be started yet */
if (isdn_net_device_started(m))
return -EBUSY;
return isdn_net_new(p+1, &m->dev);
return isdn_net_new(p+1, &m->local.dev);
}
static int
isdn_net_set_encap(isdn_net_dev *p, int encap)
isdn_net_set_encap(isdn_net_dev *idev, int encap)
{
isdn_net_local *lp = &p->local;
isdn_net_local *lp = &idev->local;
int retval = 0;
if (lp->p_encap == encap){
......@@ -1689,7 +1675,7 @@ isdn_net_set_encap(isdn_net_dev *p, int encap)
retval = 0;
goto out;
}
if (isdn_net_device_started(p)) {
if (isdn_net_device_started(idev)) {
retval = -EBUSY;
goto out;
}
......@@ -1706,11 +1692,11 @@ isdn_net_set_encap(isdn_net_dev *p, int encap)
lp->p_encap = encap;
lp->ops = netif_ops[encap];
p->dev.hard_header = lp->ops->hard_header;
p->dev.do_ioctl = lp->ops->do_ioctl;
p->dev.flags = lp->ops->flags;
p->dev.type = lp->ops->type;
p->dev.addr_len = lp->ops->addr_len;
lp->dev.hard_header = lp->ops->hard_header;
lp->dev.do_ioctl = lp->ops->do_ioctl;
lp->dev.flags = lp->ops->flags;
lp->dev.type = lp->ops->type;
lp->dev.addr_len = lp->ops->addr_len;
if (lp->ops->init)
retval = lp->ops->init(lp);
......@@ -1941,12 +1927,12 @@ isdn_net_getcfg(isdn_net_ioctl_cfg * cfg)
cfg->pppbind = idev->pppbind;
cfg->dialtimeout = lp->dialtimeout >= 0 ? lp->dialtimeout / HZ : -1;
cfg->dialwait = lp->dialwait / HZ;
if (lp->slave)
strcpy(cfg->slave, ((isdn_net_local *) lp->slave->priv)->netdev->name);
if (idev->slave)
strcpy(cfg->slave, idev->slave->name);
else
cfg->slave[0] = '\0';
if (lp->master)
strcpy(cfg->master, ((isdn_net_local *) lp->master->priv)->netdev->name);
if (idev->master)
strcpy(cfg->master, idev->master->netdev->name);
else
cfg->master[0] = '\0';
......@@ -2103,7 +2089,7 @@ int
isdn_net_force_hangup(char *name)
{
isdn_net_dev *idev = isdn_net_findif(name);
struct net_device *q;
isdn_net_dev *p;
if (!idev)
return -ENODEV;
......@@ -2111,11 +2097,11 @@ isdn_net_force_hangup(char *name)
if (idev->isdn_slot < 0)
return -ENOTCONN;
q = idev->local.slave;
p = idev->slave;
/* If this interface has slaves, do a hangup for them also. */
while (q) {
isdn_net_hangup(((isdn_net_local *) q->priv)->netdev);
q = (((isdn_net_local *) q->priv)->slave);
while (p) {
isdn_net_hangup(p);
p = p->slave;
}
isdn_net_hangup(idev);
return 0;
......@@ -2142,19 +2128,19 @@ isdn_net_realrm(isdn_net_dev *p)
/* If interface is bound exclusive, free channel-usage */
if (p->exclusive >= 0)
isdn_unexclusive_channel(p->pre_device, p->pre_channel);
if (p->local.master) {
if (p->master) {
/* It's a slave-device, so update master's slave-pointer if necessary */
if (((isdn_net_local *) (p->local.master->priv))->slave == &p->dev)
((isdn_net_local *) (p->local.master->priv))->slave = p->local.slave;
if (p->master->netdev->slave == p)
p->master->netdev->slave = p->slave;
} else {
/* Unregister only if it's a master-device */
unregister_netdev(&p->dev);
unregister_netdev(&p->local.dev);
}
/* Unlink device from chain */
list_del(&p->global_list);
if (p->local.slave) {
if (p->slave) {
/* If this interface has a slave, remove it also */
char *slavename = ((isdn_net_local *) (p->local.slave->priv))->netdev->name;
char *slavename = p->slave->name;
struct list_head *l;
list_for_each(l, &isdn_net_devs) {
......@@ -2204,7 +2190,7 @@ isdn_net_rmall(void)
isdn_net_dev *p = list_entry(isdn_net_devs.next, isdn_net_dev, global_list);
/* Remove master-devices only, slaves get removed with their master */
if (!p->local.master) {
if (!p->master) {
if ((ret = isdn_net_realrm(p))) {
restore_flags(flags);
return ret;
......@@ -2229,10 +2215,10 @@ isdn_iptyp_header(struct sk_buff *skb, struct net_device *dev,
}
static void
isdn_iptyp_receive(isdn_net_dev *p, isdn_net_local *olp,
isdn_iptyp_receive(isdn_net_local *lp, isdn_net_dev *idev,
struct sk_buff *skb)
{
isdn_net_reset_huptimer(p, olp->netdev);
isdn_net_reset_huptimer(lp, idev);
get_u16(skb->data, &skb->protocol);
skb_pull(skb, 2);
netif_rx(skb);
......@@ -2260,10 +2246,10 @@ isdn_uihdlc_header(struct sk_buff *skb, struct net_device *dev,
}
static void
isdn_uihdlc_receive(isdn_net_dev *p, isdn_net_local *olp,
isdn_uihdlc_receive(isdn_net_local *lp, isdn_net_dev *idev,
struct sk_buff *skb)
{
isdn_net_reset_huptimer(p, olp->netdev);
isdn_net_reset_huptimer(lp, idev);
skb_pull(skb, 2);
skb->protocol = htons(ETH_P_IP);
netif_rx(skb);
......@@ -2282,10 +2268,10 @@ static struct isdn_netif_ops uihdlc_ops = {
// ======================================================================
static void
isdn_rawip_receive(isdn_net_dev *p, isdn_net_local *olp,
isdn_rawip_receive(isdn_net_local *lp, isdn_net_dev *idev,
struct sk_buff *skb)
{
isdn_net_reset_huptimer(p, olp->netdev);
isdn_net_reset_huptimer(lp, idev);
skb->protocol = htons(ETH_P_IP);
netif_rx(skb);
}
......@@ -2355,10 +2341,10 @@ isdn_eth_type_trans(struct sk_buff *skb, struct net_device *dev)
}
static void
isdn_ether_receive(isdn_net_dev *p, isdn_net_local *olp,
isdn_ether_receive(isdn_net_local *lp, isdn_net_dev *idev,
struct sk_buff *skb)
{
isdn_net_reset_huptimer(p, olp->netdev);
isdn_net_reset_huptimer(lp, idev);
skb->protocol = isdn_eth_type_trans(skb, skb->dev);
netif_rx(skb);
}
......@@ -2366,7 +2352,7 @@ isdn_ether_receive(isdn_net_dev *p, isdn_net_local *olp,
static int
isdn_ether_open(isdn_net_local *lp)
{
struct net_device *dev = &lp->netdev->dev;
struct net_device *dev = &lp->dev;
struct in_device *in_dev;
int i;
......@@ -2386,7 +2372,7 @@ isdn_ether_open(isdn_net_local *lp)
static int
isdn_ether_init(isdn_net_local *lp)
{
struct net_device *dev = &lp->netdev->dev;
struct net_device *dev = &lp->dev;
ether_setup(dev);
dev->tx_queue_len = 10;
......
......@@ -58,10 +58,10 @@ extern void isdn_net_write_super(isdn_net_dev *, struct sk_buff *skb);
extern int isdn_net_online(isdn_net_dev *);
static inline void
isdn_net_reset_huptimer(isdn_net_dev *idev, isdn_net_dev *idev2)
isdn_net_reset_huptimer(isdn_net_local *lp, isdn_net_dev *idev)
{
lp->netdev->huptimer = 0;
idev->huptimer = 0;
idev2->huptimer = 0;
}
#define ISDN_NET_MAX_QUEUE_LENGTH 2
......@@ -83,76 +83,75 @@ isdn_net_dev_busy(isdn_net_dev *idev)
* corresponding bundle. The returned channel is locked.
*/
static inline isdn_net_dev *
isdn_net_get_locked_dev(isdn_net_dev *nd)
isdn_net_get_locked_dev(isdn_net_local *mlp)
{
unsigned long flags;
isdn_net_local *lp;
isdn_net_dev *idev;
isdn_net_dev *head;
spin_lock_irqsave(&nd->queue_lock, flags);
lp = nd->queue; /* get lp on top of queue */
idev = nd->queue->netdev;
spin_lock_irqsave(&mlp->queue_lock, flags);
head = mlp->queue;
idev = head;
spin_lock_bh(&idev->xmit_lock);
while (isdn_net_dev_busy(idev)) {
spin_unlock_bh(&idev->xmit_lock);
nd->queue = nd->queue->next;
idev = nd->queue->netdev;
if (nd->queue == lp) { /* not found -- should never happen */
lp = NULL;
mlp->queue = mlp->queue->next;
idev = mlp->queue;
if (idev == head) { /* not found -- should never happen */
idev = NULL;
goto errout;
}
spin_lock_bh(&idev->xmit_lock);
}
lp = nd->queue;
nd->queue = nd->queue->next;
idev = mlp->queue;
mlp->queue = mlp->queue->next;
errout:
spin_unlock_irqrestore(&nd->queue_lock, flags);
return lp ? lp->netdev : NULL;
spin_unlock_irqrestore(&mlp->queue_lock, flags);
return idev;
}
/*
* add a channel to a bundle
*/
static inline void
isdn_net_add_to_bundle(isdn_net_dev *nd, isdn_net_local *nlp)
isdn_net_add_to_bundle(isdn_net_local *mlp, isdn_net_dev *idev)
{
isdn_net_local *lp;
isdn_net_dev *qdev;
unsigned long flags;
spin_lock_irqsave(&nd->queue_lock, flags);
spin_lock_irqsave(&mlp->queue_lock, flags);
lp = nd->queue;
nlp->last = lp->last;
lp->last->next = nlp;
lp->last = nlp;
nlp->next = lp;
nd->queue = nlp;
qdev = mlp->queue;
idev->last = qdev->last;
qdev->last->next = idev;
qdev->last = idev;
idev->next = qdev;
mlp->queue = idev;
spin_unlock_irqrestore(&nd->queue_lock, flags);
spin_unlock_irqrestore(&mlp->queue_lock, flags);
}
/*
* remove a channel from the bundle it belongs to
*/
static inline void
isdn_net_rm_from_bundle(isdn_net_local *lp)
isdn_net_rm_from_bundle(isdn_net_dev *idev)
{
isdn_net_local *master_lp = lp;
isdn_net_local *mlp;
unsigned long flags;
if (lp->master)
master_lp = (isdn_net_local *) lp->master->priv;
if (idev->master)
mlp = idev->master;
else
mlp = &idev->local;
spin_lock_irqsave(&master_lp->netdev->queue_lock, flags);
lp->last->next = lp->next;
lp->next->last = lp->last;
if (master_lp->netdev->queue == lp) {
master_lp->netdev->queue = lp->next;
if (lp->next == lp) { /* last in queue */
master_lp->netdev->queue = &master_lp->netdev->local;
}
spin_lock_irqsave(&mlp->queue_lock, flags);
idev->last->next = idev->next;
idev->next->last = idev->last;
if (mlp->queue == idev) {
mlp->queue = idev->next;
}
lp->next = lp->last = lp; /* (re)set own pointers */
spin_unlock_irqrestore(&master_lp->netdev->queue_lock, flags);
idev->next = idev->last = idev; /* (re)set own pointers */
spin_unlock_irqrestore(&mlp->queue_lock, flags);
}
/*
......@@ -162,12 +161,10 @@ isdn_net_rm_from_bundle(isdn_net_local *lp)
static inline void
isdn_net_dev_wake_queue(isdn_net_dev *idev)
{
isdn_net_local *lp = &idev->local;
if (lp->master)
netif_wake_queue(lp->master);
if (idev->master)
netif_wake_queue(&idev->master->dev);
else
netif_wake_queue(&lp->netdev->dev);
netif_wake_queue(&idev->local.dev);
}
static inline int
......
......@@ -23,7 +23,7 @@
/* Prototypes */
static int isdn_ppp_fill_rq(unsigned char *buf, int len, int proto, int slot);
static int isdn_ppp_closewait(int slot);
static void isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp,
static void isdn_ppp_push_higher(isdn_net_local *lp, isdn_net_dev *idev,
struct sk_buff *skb, int proto);
static int isdn_ppp_if_get_unit(char *namebuf);
static int isdn_ppp_set_compressor(struct ippp_struct *is,struct isdn_ppp_comp_data *);
......@@ -59,10 +59,10 @@ static void isdn_ppp_ccp_reset_ack_rcvd(struct ippp_struct *is,
static ippp_bundle * isdn_ppp_bundle_arr = NULL;
static int isdn_ppp_mp_bundle_array_init(void);
static int isdn_ppp_mp_init( isdn_net_local * lp, ippp_bundle * add_to );
static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp,
static int isdn_ppp_mp_init(isdn_net_local *lp, ippp_bundle *add_to);
static void isdn_ppp_mp_receive(isdn_net_local *lp, isdn_net_dev *idev,
struct sk_buff *skb);
static void isdn_ppp_mp_cleanup( isdn_net_local * lp );
static void isdn_ppp_mp_cleanup(isdn_net_local *lp );
static int isdn_ppp_bundle(struct ippp_struct *, int unit);
#endif /* CONFIG_ISDN_MPP */
......@@ -118,7 +118,7 @@ isdn_ppp_free(isdn_net_local * lp)
#ifdef CONFIG_ISDN_MPP
spin_lock(&lp->netdev->pb->lock);
#endif
isdn_net_rm_from_bundle(lp);
isdn_net_rm_from_bundle(idev);
#ifdef CONFIG_ISDN_MPP
if (lp->netdev->pb->ref_ct == 1) /* last link in queue? */
isdn_ppp_mp_cleanup(lp);
......@@ -477,7 +477,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 (idev) {
/* OK .. we are ready to send buffers */
netif_wake_queue(&idev->dev);
netif_wake_queue(&idev->local.dev);
}
}
is->pppcfg = val;
......@@ -902,10 +902,9 @@ static int isdn_ppp_strip_proto(struct sk_buff *skb)
/*
* handler for incoming packets on a syncPPP interface
*/
static void isdn_ppp_receive(isdn_net_dev *net_dev, isdn_net_local *lp,
static void isdn_ppp_receive(isdn_net_local *lp, isdn_net_dev *idev,
struct sk_buff *skb)
{
isdn_net_dev *idev = lp->netdev;
struct ippp_struct *is;
int slot;
int proto;
......@@ -915,7 +914,7 @@ static void isdn_ppp_receive(isdn_net_dev *net_dev, isdn_net_local *lp,
* huptimer on LCP packets.
*/
if (PPP_PROTOCOL(skb->data) != PPP_LCP)
isdn_net_reset_huptimer(net_dev,lp->netdev);
isdn_net_reset_huptimer(lp, idev);
slot = idev->ppp_slot;
if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
......@@ -951,12 +950,12 @@ static void isdn_ppp_receive(isdn_net_dev *net_dev, isdn_net_local *lp,
if (!(is->mpppcfg & SC_REJ_MP_PROT)) { // we agreed to receive MPPP
if (proto == PPP_MP) {
isdn_ppp_mp_receive(net_dev, lp, skb);
isdn_ppp_mp_receive(lp, idev, skb);
return;
}
}
#endif
isdn_ppp_push_higher(net_dev, lp, skb, proto);
isdn_ppp_push_higher(lp, idev, skb, proto);
}
/*
......@@ -965,10 +964,10 @@ static void isdn_ppp_receive(isdn_net_dev *net_dev, isdn_net_local *lp,
* note: net_dev has to be master net_dev
*/
static void
isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff *skb, int proto)
isdn_ppp_push_higher(isdn_net_local *lp, isdn_net_dev *idev,
struct sk_buff *skb, int proto)
{
isdn_net_dev *idev = lp->netdev;
struct net_device *dev = &net_dev->dev;
struct net_device *dev = &lp->dev;
struct ippp_struct *is, *mis;
int slot;
......@@ -980,8 +979,8 @@ isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff
}
is = ippp_table[slot];
if (lp->master) { // FIXME?
slot = ((isdn_net_local *) (lp->master->priv))->netdev->ppp_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);
......@@ -1018,12 +1017,12 @@ isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff
case PPP_VJC_UNCOMP:
if (is->debug & 0x20)
printk(KERN_DEBUG "isdn_ppp: VJC_UNCOMP\n");
if (net_dev->ppp_slot < 0) {
if (lp->netdev->ppp_slot < 0) {
printk(KERN_ERR "%s: net_dev->ppp_slot(%d) out of range\n",
__FUNCTION__ , net_dev->ppp_slot);
__FUNCTION__ , lp->netdev->ppp_slot);
goto drop_packet;
}
if (slhc_remember(ippp_table[net_dev->ppp_slot]->slcomp, skb->data, skb->len) <= 0) {
if (slhc_remember(ippp_table[lp->netdev->ppp_slot]->slcomp, skb->data, skb->len) <= 0) {
printk(KERN_WARNING "isdn_ppp: received illegal VJC_UNCOMP frame!\n");
goto drop_packet;
}
......@@ -1044,12 +1043,12 @@ isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff
}
skb_put(skb, skb_old->len + 128);
memcpy(skb->data, skb_old->data, skb_old->len);
if (net_dev->ppp_slot < 0) {
if (lp->netdev->ppp_slot < 0) {
printk(KERN_ERR "%s: net_dev->ppp_slot(%d) out of range\n",
__FUNCTION__ , net_dev->ppp_slot);
__FUNCTION__ , lp->netdev->ppp_slot);
goto drop_packet;
}
pkt_len = slhc_uncompress(ippp_table[net_dev->ppp_slot]->slcomp,
pkt_len = slhc_uncompress(ippp_table[lp->netdev->ppp_slot]->slcomp,
skb->data, skb_old->len);
kfree_skb(skb_old);
if (pkt_len < 0)
......@@ -1062,7 +1061,7 @@ isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff
#endif
case PPP_CCP:
case PPP_CCPFRAG:
isdn_ppp_receive_ccp(net_dev,lp,skb,proto);
isdn_ppp_receive_ccp(lp->netdev,lp,skb,proto);
/* Dont pop up ResetReq/Ack stuff to the daemon any
longer - the job is done already */
if(skb->data[0] == CCP_RESETREQ ||
......@@ -1085,7 +1084,7 @@ isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff
return;
drop_packet:
net_dev->local.stats.rx_dropped++;
lp->stats.rx_dropped++;
kfree_skb(skb);
}
......@@ -1133,7 +1132,7 @@ isdn_ppp_xmit(struct sk_buff *skb, struct net_device *netdev)
struct ippp_struct *ipt,*ipts;
int slot;
mlp = (isdn_net_local *) (netdev->priv);
mlp = netdev->priv;
nd = mlp->netdev; /* get master lp */
slot = nd->ppp_slot;
......@@ -1165,7 +1164,7 @@ isdn_ppp_xmit(struct sk_buff *skb, struct net_device *netdev)
return 0;
}
idev = isdn_net_get_locked_dev(nd);
idev = isdn_net_get_locked_dev(mlp);
if (!idev) {
printk(KERN_WARNING "%s: all channels busy - requeuing!\n", netdev->name);
return 1;
......@@ -1397,7 +1396,7 @@ static int isdn_ppp_mp_init( isdn_net_local * lp, ippp_bundle * add_to )
is->mp_seqno = 0;
if ((lp->netdev->pb = isdn_ppp_mp_bundle_alloc()) == NULL)
return -ENOMEM;
lp->next = lp->last = lp; /* nobody else in a queue */
idev->next = idev->last = idev; /* nobody else in a queue */
lp->netdev->pb->frags = NULL;
lp->netdev->pb->frames = 0;
lp->netdev->pb->seq = LONG_MAX;
......@@ -1417,12 +1416,12 @@ static void isdn_ppp_mp_reassembly( isdn_net_dev * net_dev, isdn_net_local * lp,
static void isdn_ppp_mp_free_skb( ippp_bundle * mp, struct sk_buff * skb );
static void isdn_ppp_mp_print_recv_pkt( int slot, struct sk_buff * skb );
static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp,
static void isdn_ppp_mp_receive(isdn_net_local *lp, isdn_net_dev *dev,
struct sk_buff *skb)
{
isdn_net_dev *idev = lp->netdev;
struct ippp_struct *is;
isdn_net_local * lpq;
isdn_net_dev *qdev;
ippp_bundle * mp;
isdn_mppp_stats * stats;
struct sk_buff * newfrag, * frag, * start, *nextf;
......@@ -1430,8 +1429,8 @@ static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp,
unsigned long flags;
int slot;
spin_lock_irqsave(&net_dev->pb->lock, flags);
mp = net_dev->pb;
spin_lock_irqsave(&lp->netdev->pb->lock, flags);
mp = lp->netdev->pb;
stats = &mp->stats;
slot = idev->ppp_slot;
if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
......@@ -1469,8 +1468,8 @@ static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp,
/* find the minimum received sequence number over all links */
is->last_link_seqno = minseq = newseq;
for (lpq = net_dev->queue;;) {
slot = lpq->netdev->ppp_slot;
for (qdev = lp->queue;;) {
slot = qdev->ppp_slot;
if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
printk(KERN_ERR "%s: lpq->ppp_slot(%d)\n",
__FUNCTION__ ,slot);
......@@ -1479,7 +1478,7 @@ static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp,
if (MP_LT(lls, minseq))
minseq = lls;
}
if ((lpq = lpq->next) == net_dev->queue)
if ((qdev = qdev->next) == lp->queue)
break;
}
if (MP_LT(minseq, mp->seq))
......@@ -1569,7 +1568,7 @@ static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp,
if (start != NULL && (MP_FLAGS(frag) & MP_END_FRAG)) {
minseq = mp->seq = (thisseq+1) & MP_LONGSEQ_MASK;
/* Reassemble the packet then dispatch it */
isdn_ppp_mp_reassembly(net_dev, lp, start, nextf);
isdn_ppp_mp_reassembly(lp->netdev, lp, start, nextf);
start = NULL;
frag = NULL;
......@@ -1746,7 +1745,7 @@ void isdn_ppp_mp_reassembly( isdn_net_dev * net_dev, isdn_net_local * lp,
}
}
proto = isdn_ppp_strip_proto(skb);
isdn_ppp_push_higher(net_dev, lp, skb, proto);
isdn_ppp_push_higher(lp, idev, skb, proto);
}
static void isdn_ppp_mp_free_skb(ippp_bundle * mp, struct sk_buff * skb)
......@@ -1782,7 +1781,7 @@ isdn_ppp_bundle(struct ippp_struct *is, int unit)
spin_lock_irqsave(&p->pb->lock, flags);
nidev = is->idev;
idev = p->queue->netdev;
idev = p->local.queue;
if( nidev->ppp_slot < 0 || nidev->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",
......@@ -1792,7 +1791,7 @@ isdn_ppp_bundle(struct ippp_struct *is, int unit)
goto out;
}
isdn_net_add_to_bundle(p, &nidev->local);
isdn_net_add_to_bundle(&p->local, nidev);
ippp_table[nidev->ppp_slot]->unit = ippp_table[idev->ppp_slot]->unit;
......@@ -1916,7 +1915,7 @@ isdn_ppp_dial_slave(char *name)
#ifdef CONFIG_ISDN_MPP
isdn_net_dev *idev;
isdn_net_local *lp;
struct net_device *sdev;
isdn_net_dev *sdev;
idev = isdn_net_findif(name);
if (!idev)
......@@ -1926,17 +1925,16 @@ isdn_ppp_dial_slave(char *name)
if (!isdn_net_bound(idev))
return 5;
sdev = lp->slave;
sdev = idev->slave;
while (sdev) {
isdn_net_local *mlp = (isdn_net_local *) sdev->priv;
if (!isdn_net_bound(mlp->netdev))
if (!isdn_net_bound(sdev))
break;
sdev = mlp->slave;
sdev = sdev->slave;
}
if (!sdev)
return 2;
isdn_net_dial_req(((isdn_net_local *) sdev->priv)->netdev);
isdn_net_dial_req(sdev);
return 0;
#else
return -1;
......@@ -1947,35 +1945,20 @@ int
isdn_ppp_hangup_slave(char *name)
{
#ifdef CONFIG_ISDN_MPP
isdn_net_dev *idev;
isdn_net_local *lp, *mlp = NULL;
struct net_device *sdev;
isdn_net_dev *idev, *sdev;
idev = isdn_net_findif(name);
if (!idev)
return 1;
lp = &idev->local;
if (!isdn_net_bound(idev))
return 5;
sdev = lp->slave;
while (sdev) {
mlp = (isdn_net_local *) sdev->priv;
if (mlp->slave) { /* find last connected link in chain */
isdn_net_local *nlp = (isdn_net_local *) mlp->slave->priv;
if (!isdn_net_bound(nlp->netdev))
break;
} else if (isdn_net_bound(mlp->netdev))
break;
sdev = mlp->slave;
}
if (!sdev)
sdev = idev->slave;
if (!sdev || !isdn_net_bound(sdev))
return 2;
isdn_net_hangup(mlp->netdev);
isdn_net_hangup(sdev);
return 0;
#else
return -1;
......@@ -2495,8 +2478,8 @@ static void isdn_ppp_receive_ccp(isdn_net_dev *net_dev, isdn_net_local *lp,
is = ippp_table[idev->ppp_slot];
isdn_ppp_frame_log("ccp-rcv", skb->data, skb->len, 32, is->unit,idev->ppp_slot);
if(lp->master) {
int slot = ((isdn_net_local *) (lp->master->priv))->netdev->ppp_slot;
if (idev->master) {
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);
......@@ -2683,8 +2666,8 @@ 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");
isdn_ppp_frame_log("ccp-xmit", skb->data, skb->len, 32, is->unit,idev->ppp_slot);
if (lp->master) {
slot = ((isdn_net_local *) (lp->master->priv))->netdev->ppp_slot;
if (idev->master) {
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);
......
......@@ -294,8 +294,8 @@ struct isdn_netif_ops {
unsigned short flags; /* interface flags (a la BSD) */
unsigned short type; /* interface hardware type */
unsigned char addr_len;/* hardware address length */
void (*receive)(struct isdn_net_dev_s *p,
struct isdn_net_local_s *olp,
void (*receive)(struct isdn_net_local_s *lp,
struct isdn_net_dev_s *idev,
struct sk_buff *skb);
void (*connected)(struct isdn_net_local_s *lp);
void (*disconnected)(struct isdn_net_local_s *lp);
......@@ -334,12 +334,13 @@ typedef struct isdn_net_local_s {
struct list_head phone[2]; /* List of remote-phonenumbers */
/* phone[0] = Incoming Numbers */
/* phone[1] = Outgoing Numbers */
struct net_device *master; /* Ptr to Master device for slaves */
struct net_device *slave; /* Ptr to Slave device for masters */
struct isdn_net_local_s *next; /* Ptr to next link in bundle */
struct isdn_net_local_s *last; /* Ptr to last link in bundle */
struct isdn_net_dev_s *netdev; /* Ptr to netdev */
struct isdn_net_dev_s *queue; /* circular list of all bundled
channels, which are currently
online */
spinlock_t queue_lock; /* lock to protect queue */
#ifdef CONFIG_ISDN_X25
struct concap_device_ops *dops; /* callbacks used by encapsulator */
#endif
......@@ -352,7 +353,10 @@ typedef struct isdn_net_local_s {
char cisco_line_state; /* state of line according to keepalive packets */
char cisco_debserint; /* debugging flag of cisco hdlc with slarp */
struct timer_list cisco_timer;
struct isdn_netif_ops *ops;
struct net_device dev; /* interface to upper levels */
} isdn_net_local;
/* the interface itself */
......@@ -397,13 +401,15 @@ typedef struct isdn_net_dev_s {
/* queued in HL driver */
struct tq_struct tqueue;
isdn_net_local *queue; /* circular list of all bundled
channels, which are currently
online */
spinlock_t queue_lock; /* lock to protect queue */
isdn_net_local *master; /* Ptr to Master device for slaves */
struct isdn_net_dev_s *slave; /* Ptr to Slave device for masters */
struct isdn_net_dev_s *next; /* Ptr to next link in bundle */
struct isdn_net_dev_s *last; /* Ptr to last link in bundle */
char name[10]; /* Name of device */
struct list_head global_list; /* global list of all isdn_net_devs */
struct net_device dev; /* interface to upper levels */
#ifdef CONFIG_ISDN_PPP
ippp_bundle * pb; /* pointer to the common bundle structure
* with the per-bundle data */
......
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